fluent-plugin-kinesis 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ #
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
+
15
+ source 'https://rubygems.org'
16
+
17
+ # Specify your gem's dependencies in fluent-plugin-kinesis.gemspec
18
+ gemspec path: ".."
19
+
20
+ # Specify related gems for td-agent v3.2.0
21
+ # https://github.com/treasure-data/omnibus-td-agent/blob/v3.2.0/config/projects/td-agent3.rb#L27
22
+ gem "fluentd", "1.2.2"
23
+ # https://github.com/treasure-data/omnibus-td-agent/blob/v3.2.0/plugin_gems.rb#L16-L23
24
+ gem "jmespath", "1.4.0"
25
+ gem "aws-partitions", "1.87.0"
26
+ gem "aws-sigv4", "1.0.2"
27
+ gem "aws-sdk-core", "3.21.2"
28
+ gem "aws-sdk-kms", "1.5.0"
29
+ gem "aws-sdk-sqs", "1.3.0"
30
+ gem "aws-sdk-s3", "1.13.0"
31
+ gem "fluent-plugin-s3", "1.1.3"
@@ -0,0 +1,31 @@
1
+ #
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
+
15
+ source 'https://rubygems.org'
16
+
17
+ # Specify your gem's dependencies in fluent-plugin-kinesis.gemspec
18
+ gemspec path: ".."
19
+
20
+ # Specify related gems for td-agent v3.2.1
21
+ # https://github.com/treasure-data/omnibus-td-agent/blob/v3.2.1/config/projects/td-agent3.rb#L27
22
+ gem "fluentd", "1.2.6"
23
+ # https://github.com/treasure-data/omnibus-td-agent/blob/v3.2.1/plugin_gems.rb#L16-L23
24
+ gem "jmespath", "1.4.0"
25
+ gem "aws-partitions", "1.105.0"
26
+ gem "aws-sigv4", "1.0.3"
27
+ gem "aws-sdk-core", "3.30.0"
28
+ gem "aws-sdk-kms", "1.9.0"
29
+ gem "aws-sdk-sqs", "1.7.0"
30
+ gem "aws-sdk-s3", "1.21.0"
31
+ gem "fluent-plugin-s3", "1.1.6"
@@ -0,0 +1,31 @@
1
+ #
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
+
15
+ source 'https://rubygems.org'
16
+
17
+ # Specify your gem's dependencies in fluent-plugin-kinesis.gemspec
18
+ gemspec path: ".."
19
+
20
+ # Specify related gems for td-agent v3.3.0
21
+ # https://github.com/treasure-data/omnibus-td-agent/blob/v3.3.0/config/projects/td-agent3.rb#L27
22
+ gem "fluentd", "1.3.3"
23
+ # https://github.com/treasure-data/omnibus-td-agent/blob/v3.3.0/plugin_gems.rb#L16-L23
24
+ gem "jmespath", "1.4.0"
25
+ gem "aws-partitions", "1.127.0"
26
+ gem "aws-sigv4", "1.0.3"
27
+ gem "aws-sdk-core", "3.44.2"
28
+ gem "aws-sdk-kms", "1.13.0"
29
+ gem "aws-sdk-sqs", "1.10.0"
30
+ gem "aws-sdk-s3", "1.30.0"
31
+ gem "fluent-plugin-s3", "1.1.7"
@@ -12,154 +12,149 @@
12
12
  # ANY KIND, either express or implied. See the License for the specific
13
13
  # language governing permissions and limitations under the License.
14
14
 
15
+ require 'fluent/plugin/output'
15
16
  require 'fluent/plugin/kinesis_helper/client'
16
17
  require 'fluent/plugin/kinesis_helper/api'
17
18
  require 'zlib'
18
19
 
19
20
  module Fluent
20
- class KinesisOutput < BufferedOutput
21
- def self.fluentd_v0_12?
22
- @fluentd_v0_12 ||= Gem.loaded_specs['fluentd'].version < Gem::Version.create('0.14')
23
- end
24
-
25
- include Fluent::SetTimeKeyMixin
26
- include Fluent::SetTagKeyMixin
27
-
28
- include KinesisHelper::Client
29
- include KinesisHelper::API
30
-
31
- class SkipRecordError < ::StandardError
32
- def initialize(message, record)
33
- super message
34
- @record_message = if record.is_a? Array
35
- record.reverse.map(&:to_s).join(', ')
36
- else
37
- record.to_s
21
+ module Plugin
22
+ class KinesisOutput < Fluent::Plugin::Output
23
+ include Fluent::MessagePackFactory::Mixin
24
+ include KinesisHelper::Client
25
+ include KinesisHelper::API
26
+
27
+ class SkipRecordError < ::StandardError
28
+ def initialize(message, record)
29
+ super message
30
+ @record_message = if record.is_a? Array
31
+ record.reverse.map(&:to_s).join(', ')
32
+ else
33
+ record.to_s
34
+ end
38
35
  end
39
- end
40
36
 
41
- def to_s
42
- super + ": " + @record_message
37
+ def to_s
38
+ super + ": " + @record_message
39
+ end
43
40
  end
44
- end
45
- class KeyNotFoundError < SkipRecordError
46
- def initialize(key, record)
47
- super "Key '#{key}' doesn't exist", record
41
+ class KeyNotFoundError < SkipRecordError
42
+ def initialize(key, record)
43
+ super "Key '#{key}' doesn't exist", record
44
+ end
48
45
  end
49
- end
50
- class ExceedMaxRecordSizeError < SkipRecordError
51
- def initialize(size, record)
52
- super "Record size limit exceeded in #{size/1024} KB", record
46
+ class ExceedMaxRecordSizeError < SkipRecordError
47
+ def initialize(size, record)
48
+ super "Record size limit exceeded in #{size/1024} KB", record
49
+ end
53
50
  end
54
- end
55
- class InvalidRecordError < SkipRecordError
56
- def initialize(record)
57
- super "Invalid type of record", record
51
+ class InvalidRecordError < SkipRecordError
52
+ def initialize(record)
53
+ super "Invalid type of record", record
54
+ end
58
55
  end
59
- end
60
56
 
61
- config_param :data_key, :string, default: nil
62
- config_param :log_truncate_max_size, :integer, default: 1024
63
- config_param :compression, :string, default: nil
64
- config_section :format do
65
- config_set_default :@type, 'json'
66
- end
67
- config_section :inject do
68
- config_set_default :time_type, 'string'
69
- config_set_default :time_format, '%Y-%m-%dT%H:%M:%S.%N%z'
70
- end
57
+ config_param :data_key, :string, default: nil
58
+ config_param :log_truncate_max_size, :integer, default: 1024
59
+ config_param :compression, :string, default: nil
71
60
 
72
- config_param :debug, :bool, default: false
61
+ desc "Formatter calls chomp and removes separator from the end of each record. This option is for compatible format with plugin v2. (default: false)"
62
+ # https://github.com/awslabs/aws-fluent-plugin-kinesis/issues/142
63
+ config_param :chomp_record, :bool, default: false
73
64
 
74
- if fluentd_v0_12?
75
- config_param :format, :string, default: 'json'
76
- else
77
- helpers :formatter, :inject
78
- end
65
+ config_section :format do
66
+ config_set_default :@type, 'json'
67
+ end
68
+ config_section :inject do
69
+ config_set_default :time_type, 'string'
70
+ config_set_default :time_format, '%Y-%m-%dT%H:%M:%S.%N%z'
71
+ end
79
72
 
80
- def configure(conf)
81
- super
82
- @data_formatter = data_formatter_create(conf)
83
- end
73
+ config_param :debug, :bool, default: false
84
74
 
85
- def multi_workers_ready?
86
- true
87
- end
75
+ helpers :formatter, :inject
88
76
 
89
- private
77
+ def configure(conf)
78
+ super
79
+ @data_formatter = data_formatter_create(conf)
80
+ end
90
81
 
91
- def fluentd_v0_12?
92
- self.class.fluentd_v0_12?
93
- end
82
+ def multi_workers_ready?
83
+ true
84
+ end
85
+
86
+ private
94
87
 
95
- def data_formatter_create(conf)
96
- if fluentd_v0_12?
97
- formatter = Fluent::Plugin.new_formatter(@format)
98
- formatter.configure(conf)
99
- else
88
+ def data_formatter_create(conf)
100
89
  formatter = formatter_create
101
- end
102
- compressor = compressor_create
103
- if @data_key.nil?
104
- ->(tag, time, record) {
105
- unless fluentd_v0_12?
106
- record = inject_values_to_record(tag, time, record)
90
+ compressor = compressor_create
91
+ if @data_key.nil?
92
+ if @chomp_record
93
+ ->(tag, time, record) {
94
+ record = inject_values_to_record(tag, time, record)
95
+ # Formatter calls chomp and removes separator from the end of each record.
96
+ # This option is for compatible format with plugin v2.
97
+ # https://github.com/awslabs/aws-fluent-plugin-kinesis/issues/142
98
+ compressor.call(formatter.format(tag, time, record).chomp.b)
99
+ }
100
+ else
101
+ ->(tag, time, record) {
102
+ record = inject_values_to_record(tag, time, record)
103
+ compressor.call(formatter.format(tag, time, record).b)
104
+ }
107
105
  end
108
- compressor.call(formatter.format(tag, time, record).chomp.b)
109
- }
110
- else
111
- ->(tag, time, record) {
112
- raise InvalidRecordError, record unless record.is_a? Hash
113
- raise KeyNotFoundError.new(@data_key, record) if record[@data_key].nil?
114
- compressor.call(record[@data_key].to_s.b)
115
- }
106
+ else
107
+ ->(tag, time, record) {
108
+ raise InvalidRecordError, record unless record.is_a? Hash
109
+ raise KeyNotFoundError.new(@data_key, record) if record[@data_key].nil?
110
+ compressor.call(record[@data_key].to_s.b)
111
+ }
112
+ end
116
113
  end
117
- end
118
114
 
119
- def compressor_create
120
- case @compression
121
- when "zlib"
122
- ->(data) { Zlib::Deflate.deflate(data) }
123
- else
124
- ->(data) { data }
115
+ def compressor_create
116
+ case @compression
117
+ when "zlib"
118
+ ->(data) { Zlib::Deflate.deflate(data) }
119
+ else
120
+ ->(data) { data }
121
+ end
125
122
  end
126
- end
127
123
 
128
- def format_for_api(&block)
129
- converted = block.call
130
- size = size_of_values(converted)
131
- if size > @max_record_size
132
- raise ExceedMaxRecordSizeError.new(size, converted)
124
+ def format_for_api(&block)
125
+ converted = block.call
126
+ size = size_of_values(converted)
127
+ if size > @max_record_size
128
+ raise ExceedMaxRecordSizeError.new(size, converted)
129
+ end
130
+ converted.to_msgpack
131
+ rescue SkipRecordError => e
132
+ log.error(truncate e)
133
+ ''
133
134
  end
134
- converted.to_msgpack
135
- rescue SkipRecordError => e
136
- log.error(truncate e)
137
- ''
138
- end
139
135
 
140
- def write_records_batch(chunk, &block)
141
- if fluentd_v0_12?
142
- unique_id = chunk.unique_id.unpack('H*').first
143
- else
136
+ def write_records_batch(chunk, &block)
144
137
  unique_id = chunk.dump_unique_id_hex(chunk.unique_id)
138
+ chunk.open do |io|
139
+ records = msgpack_unpacker(io).to_enum
140
+ split_to_batches(records) do |batch, size|
141
+ log.debug(sprintf "Write chunk %s / %3d records / %4d KB", unique_id, batch.size, size/1024)
142
+ batch_request_with_retry(batch, &block)
143
+ log.debug("Finish writing chunk")
144
+ end
145
+ end
145
146
  end
146
- records = chunk.to_enum(:msgpack_each)
147
- split_to_batches(records) do |batch, size|
148
- log.debug(sprintf "Write chunk %s / %3d records / %4d KB", unique_id, batch.size, size/1024)
149
- batch_request_with_retry(batch, &block)
150
- log.debug("Finish writing chunk")
151
- end
152
- end
153
147
 
154
- def request_type
155
- self.class::RequestType
156
- end
148
+ def request_type
149
+ self.class::RequestType
150
+ end
157
151
 
158
- def truncate(msg)
159
- if @log_truncate_max_size == 0 or (msg.to_s.size <= @log_truncate_max_size)
160
- msg.to_s
161
- else
162
- msg.to_s[0...@log_truncate_max_size]
152
+ def truncate(msg)
153
+ if @log_truncate_max_size == 0 or (msg.to_s.size <= @log_truncate_max_size)
154
+ msg.to_s
155
+ else
156
+ msg.to_s[0...@log_truncate_max_size]
157
+ end
163
158
  end
164
159
  end
165
160
  end
@@ -34,64 +34,66 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
34
34
  end
35
35
 
36
36
  module Fluent
37
- module KinesisHelper
38
- class Aggregator
39
- AggregatedRecord = Google::Protobuf::DescriptorPool.generated_pool.lookup("AggregatedRecord").msgclass
40
- Tag = Google::Protobuf::DescriptorPool.generated_pool.lookup("Tag").msgclass
41
- Record = Google::Protobuf::DescriptorPool.generated_pool.lookup("Record").msgclass
37
+ module Plugin
38
+ module KinesisHelper
39
+ class Aggregator
40
+ AggregatedRecord = Google::Protobuf::DescriptorPool.generated_pool.lookup("AggregatedRecord").msgclass
41
+ Tag = Google::Protobuf::DescriptorPool.generated_pool.lookup("Tag").msgclass
42
+ Record = Google::Protobuf::DescriptorPool.generated_pool.lookup("Record").msgclass
42
43
 
43
- class InvalidEncodingError < ::StandardError; end
44
+ class InvalidEncodingError < ::StandardError; end
44
45
 
45
- MagicNumber = ['F3899AC2'].pack('H*')
46
+ MagicNumber = ['F3899AC2'].pack('H*')
46
47
 
47
- def aggregate(records, partition_key)
48
- message = AggregatedRecord.encode(AggregatedRecord.new(
49
- partition_key_table: ['a', partition_key],
50
- records: records.map{|data|
51
- Record.new(partition_key_index: 1, data: data)
52
- },
53
- ))
54
- [MagicNumber, message, Digest::MD5.digest(message)].pack("A4A*A16")
55
- end
56
-
57
- def deaggregate(encoded)
58
- unless aggregated?(encoded)
59
- raise InvalidEncodingError, "Invalid MagicNumber #{encoded[0..3]}}"
48
+ def aggregate(records, partition_key)
49
+ message = AggregatedRecord.encode(AggregatedRecord.new(
50
+ partition_key_table: ['a', partition_key],
51
+ records: records.map{|data|
52
+ Record.new(partition_key_index: 1, data: data)
53
+ },
54
+ ))
55
+ [MagicNumber, message, Digest::MD5.digest(message)].pack("A4A*A16")
60
56
  end
61
- message, digest = encoded[4..encoded.length-17], encoded[encoded.length-16..-1]
62
- if Digest::MD5.digest(message) != digest
63
- raise InvalidEncodingError, "Digest mismatch #{digest}"
57
+
58
+ def deaggregate(encoded)
59
+ unless aggregated?(encoded)
60
+ raise InvalidEncodingError, "Invalid MagicNumber #{encoded[0..3]}}"
61
+ end
62
+ message, digest = encoded[4..encoded.length-17], encoded[encoded.length-16..-1]
63
+ if Digest::MD5.digest(message) != digest
64
+ raise InvalidEncodingError, "Digest mismatch #{digest}"
65
+ end
66
+ decoded = AggregatedRecord.decode(message)
67
+ records = decoded.records.map(&:data)
68
+ partition_key = decoded.partition_key_table[1]
69
+ [records, partition_key]
64
70
  end
65
- decoded = AggregatedRecord.decode(message)
66
- records = decoded.records.map(&:data)
67
- partition_key = decoded.partition_key_table[1]
68
- [records, partition_key]
69
- end
70
71
 
71
- def aggregated?(encoded)
72
- encoded[0..3] == MagicNumber
73
- end
72
+ def aggregated?(encoded)
73
+ encoded[0..3] == MagicNumber
74
+ end
74
75
 
75
- def aggregated_size_offset(partition_key)
76
- data = 'd'
77
- encoded = aggregate([record(data)], partition_key)
78
- finalize(encoded).size - data.size
79
- end
76
+ def aggregated_size_offset(partition_key)
77
+ data = 'd'
78
+ encoded = aggregate([record(data)], partition_key)
79
+ finalize(encoded).size - data.size
80
+ end
80
81
 
81
- module Mixin
82
- AggregateOffset = 25
83
- RecordOffset = 10
82
+ module Mixin
83
+ AggregateOffset = 25
84
+ RecordOffset = 10
84
85
 
85
- module Params
86
- include Fluent::Configurable
87
- end
86
+ module Params
87
+ include Fluent::Configurable
88
+ end
88
89
 
89
- def self.included(mod)
90
- mod.include Params
91
- end
90
+ def self.included(mod)
91
+ mod.include Params
92
+ end
92
93
 
93
- def aggregator
94
- @aggregator ||= Aggregator.new
94
+ def aggregator
95
+ @aggregator ||= Aggregator.new
96
+ end
95
97
  end
96
98
  end
97
99
  end