logstash-integration-kafka 10.7.2-java → 10.7.3-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ca014c7463762ed6c2f4be1a9c0dce13356980f7ddf244294dd02837862d54f
4
- data.tar.gz: 1d68b07fa127636a6bba867ffa0fff6beefd5b1d0a7ba1419eedcea224a97fe5
3
+ metadata.gz: 1049dfcad573e64aed24bebc6114b0345ce6513e43c2104c54ac8e3ed6602e57
4
+ data.tar.gz: 41260002d0a2765b4beeac73bdd8d8f100e0b3e058c1e5dbac4f2a460a29a3d0
5
5
  SHA512:
6
- metadata.gz: 97c32c1cdf91c205a61fefa6ec23544b45cbc66205418df85b2e7bb0c724a2a5672f658b947c086f38808b445d99bc053ee0651eae6b3da0e5cee6065f519c59
7
- data.tar.gz: 6f67718001a257aafa339dde326192eef009a1bd74a1c1d4e8b37ca277362f95da3a56100819d9ec972a782e0631a5e4c91013d59efab720ea8e8c39b9d100a4
6
+ metadata.gz: 744b4621e51c32ef882c7f5521be467c75805c2ba6ee8eaf225567412fe9e6bade35e60ae7fa85b87de50f68a191f5408b0504025e28071e11eb227ab5f428c8
7
+ data.tar.gz: feb75d5f0da3523e891253213cf52b49460881c125adf2fc82710f96c0feaa3eb4630468bbec7f1182c6a52e44b060362b5dd946b6194c066821a3de4c6e1314
data/CHANGELOG.md CHANGED
@@ -1,8 +1,11 @@
1
+ ## 10.7.3
2
+ - Changed `decorate_events` to add also Kafka headers [#78](https://github.com/logstash-plugins/logstash-integration-kafka/pull/78)
3
+
1
4
  ## 10.7.2
2
5
  - Update Jersey dependency to version 2.33 [#75](https://github.com/logstash-plugins/logstash-integration-kafka/pull/75)
3
6
 
4
7
  ## 10.7.1
5
- - Fix: dropped usage of SHUTDOWN event deprecated since Logstash 5.0 [#71](https://github.com/logstash-plugins/logstash-integration-kafka/issue/71)
8
+ - Fix: dropped usage of SHUTDOWN event deprecated since Logstash 5.0 [#71](https://github.com/logstash-plugins/logstash-integration-kafka/pull/71)
6
9
 
7
10
  ## 10.7.0
8
11
  - Switched use from Faraday to Manticore as HTTP client library to access Schema Registry service
@@ -73,7 +73,7 @@ either when the record was created (default) or when it was received by the
73
73
  broker. See more about property log.message.timestamp.type at
74
74
  https://kafka.apache.org/{kafka_client_doc}/documentation.html#brokerconfigs
75
75
 
76
- Metadata is only added to the event if the `decorate_events` option is set to true (it defaults to false).
76
+ Metadata is only added to the event if the `decorate_events` option is set to `basic` or `extended` (it defaults to `none`).
77
77
 
78
78
  Please note that `@metadata` fields are not part of any of your events at output time. If you need these information to be
79
79
  inserted into your original event, you'll have to use the `mutate` filter to manually copy the required fields into your `event`.
@@ -99,7 +99,7 @@ See the https://kafka.apache.org/{kafka_client_doc}/documentation for more detai
99
99
  | <<plugins-{type}s-{plugin}-client_rack>> |<<string,string>>|No
100
100
  | <<plugins-{type}s-{plugin}-connections_max_idle_ms>> |<<number,number>>|No
101
101
  | <<plugins-{type}s-{plugin}-consumer_threads>> |<<number,number>>|No
102
- | <<plugins-{type}s-{plugin}-decorate_events>> |<<boolean,boolean>>|No
102
+ | <<plugins-{type}s-{plugin}-decorate_events>> |<<string,string>>|No
103
103
  | <<plugins-{type}s-{plugin}-enable_auto_commit>> |<<boolean,boolean>>|No
104
104
  | <<plugins-{type}s-{plugin}-exclude_internal_topics>> |<<string,string>>|No
105
105
  | <<plugins-{type}s-{plugin}-fetch_max_bytes>> |<<number,number>>|No
@@ -246,10 +246,16 @@ balance — more threads than partitions means that some threads will be idl
246
246
  [id="plugins-{type}s-{plugin}-decorate_events"]
247
247
  ===== `decorate_events`
248
248
 
249
- * Value type is <<boolean,boolean>>
250
- * Default value is `false`
251
-
252
- Option to add Kafka metadata like topic, message size to the event.
249
+ * Value type is <<string,string>>
250
+ * Accepted values are:
251
+ - `none`: no metadata is added
252
+ - `basic`: record's attributes are added
253
+ - `extended`: record's attributes, headers are added
254
+ - `false`: deprecated alias for `none`
255
+ - `true`: deprecated alias for `basic`
256
+ * Default value is `none`
257
+
258
+ Option to add Kafka metadata like topic, message size and header key values to the event.
253
259
  This will add a field named `kafka` to the logstash event containing the following attributes:
254
260
 
255
261
  * `topic`: The topic this message is associated with
@@ -8,6 +8,7 @@ require 'manticore'
8
8
  require "json"
9
9
  require "logstash/json"
10
10
  require_relative '../plugin_mixins/common'
11
+ require 'logstash/plugin_mixins/deprecation_logger_support'
11
12
 
12
13
  # This input will read events from a Kafka topic. It uses the 0.10 version of
13
14
  # the consumer API provided by Kafka to read messages from the broker.
@@ -58,6 +59,7 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
58
59
 
59
60
  include LogStash::PluginMixins::KafkaSupport
60
61
  include ::LogStash::PluginMixins::KafkaAvroSchemaRegistry
62
+ include LogStash::PluginMixins::DeprecationLoggerSupport
61
63
 
62
64
  config_name 'kafka'
63
65
 
@@ -233,22 +235,49 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
233
235
  config :sasl_jaas_config, :validate => :string
234
236
  # Optional path to kerberos config file. This is krb5.conf style as detailed in https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html
235
237
  config :kerberos_config, :validate => :path
236
- # Option to add Kafka metadata like topic, message size to the event.
237
- # This will add a field named `kafka` to the logstash event containing the following attributes:
238
+ # Option to add Kafka metadata like topic, message size and header key values to the event.
239
+ # With `basic` this will add a field named `kafka` to the logstash event containing the following attributes:
238
240
  # `topic`: The topic this message is associated with
239
241
  # `consumer_group`: The consumer group used to read in this event
240
242
  # `partition`: The partition this message is associated with
241
243
  # `offset`: The offset from the partition this message is associated with
242
244
  # `key`: A ByteBuffer containing the message key
243
245
  # `timestamp`: The timestamp of this message
244
- config :decorate_events, :validate => :boolean, :default => false
246
+ # While with `extended` it adds also all the key values present in the Kafka header if the key is valid UTF-8 else
247
+ # silently skip it.
248
+ config :decorate_events, :validate => %w(none basic extended false true), :default => "none"
249
+
250
+ attr_reader :metadata_mode
245
251
 
246
252
  public
247
253
  def register
248
254
  @runner_threads = []
255
+ @metadata_mode = extract_metadata_level(@decorate_events)
249
256
  check_schema_registry_parameters
250
257
  end
251
258
 
259
+ METADATA_NONE = Set[].freeze
260
+ METADATA_BASIC = Set[:record_props].freeze
261
+ METADATA_EXTENDED = Set[:record_props, :headers].freeze
262
+ METADATA_DEPRECATION_MAP = { 'true' => 'basic', 'false' => 'none' }
263
+
264
+ private
265
+ def extract_metadata_level(decorate_events_setting)
266
+ metadata_enabled = decorate_events_setting
267
+
268
+ if METADATA_DEPRECATION_MAP.include?(metadata_enabled)
269
+ canonical_value = METADATA_DEPRECATION_MAP[metadata_enabled]
270
+ deprecation_logger.deprecated("Deprecated value `#{decorate_events_setting}` for `decorate_events` option; use `#{canonical_value}` instead.")
271
+ metadata_enabled = canonical_value
272
+ end
273
+
274
+ case metadata_enabled
275
+ when 'none' then METADATA_NONE
276
+ when 'basic' then METADATA_BASIC
277
+ when 'extended' then METADATA_EXTENDED
278
+ end
279
+ end
280
+
252
281
  public
253
282
  def run(logstash_queue)
254
283
  @runner_consumers = consumer_threads.times.map { |i| create_consumer("#{client_id}-#{i}") }
@@ -292,7 +321,7 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
292
321
  end
293
322
  event.remove("message")
294
323
  end
295
- if @decorate_events
324
+ if @metadata_mode.include?(:record_props)
296
325
  event.set("[@metadata][kafka][topic]", record.topic)
297
326
  event.set("[@metadata][kafka][consumer_group]", @group_id)
298
327
  event.set("[@metadata][kafka][partition]", record.partition)
@@ -300,6 +329,15 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
300
329
  event.set("[@metadata][kafka][key]", record.key)
301
330
  event.set("[@metadata][kafka][timestamp]", record.timestamp)
302
331
  end
332
+ if @metadata_mode.include?(:headers)
333
+ record.headers.each do |header|
334
+ s = String.from_java_bytes(header.value)
335
+ s.force_encoding(Encoding::UTF_8)
336
+ if s.valid_encoding?
337
+ event.set("[@metadata][kafka][headers]["+header.key+"]", s)
338
+ end
339
+ end
340
+ end
303
341
  logstash_queue << event
304
342
  end
305
343
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-integration-kafka'
3
- s.version = '10.7.2'
3
+ s.version = '10.7.3'
4
4
  s.licenses = ['Apache-2.0']
5
5
  s.summary = "Integration with Kafka - input and output plugins"
6
6
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline "+
@@ -47,6 +47,7 @@ Gem::Specification.new do |s|
47
47
  s.add_runtime_dependency 'logstash-codec-plain'
48
48
  s.add_runtime_dependency 'stud', '>= 0.0.22', '< 0.1.0'
49
49
  s.add_runtime_dependency "manticore", '>= 0.5.4', '< 1.0.0'
50
+ s.add_runtime_dependency 'logstash-mixin-deprecation_logger_support', '~>1.0'
50
51
 
51
52
  s.add_development_dependency 'logstash-devutils'
52
53
  s.add_development_dependency 'rspec-wait'
@@ -36,7 +36,15 @@ describe "inputs/kafka", :integration => true do
36
36
  end
37
37
  let(:decorate_config) do
38
38
  { 'topics' => ['logstash_integration_topic_plain'], 'codec' => 'plain', 'group_id' => group_id_3,
39
- 'auto_offset_reset' => 'earliest', 'decorate_events' => true }
39
+ 'auto_offset_reset' => 'earliest', 'decorate_events' => 'true' }
40
+ end
41
+ let(:decorate_headers_config) do
42
+ { 'topics' => ['logstash_integration_topic_plain_with_headers'], 'codec' => 'plain', 'group_id' => group_id_3,
43
+ 'auto_offset_reset' => 'earliest', 'decorate_events' => 'extended' }
44
+ end
45
+ let(:decorate_bad_headers_config) do
46
+ { 'topics' => ['logstash_integration_topic_plain_with_headers_badly'], 'codec' => 'plain', 'group_id' => group_id_3,
47
+ 'auto_offset_reset' => 'earliest', 'decorate_events' => 'extended' }
40
48
  end
41
49
  let(:manual_commit_config) do
42
50
  { 'topics' => ['logstash_integration_topic_plain'], 'codec' => 'plain', 'group_id' => group_id_5,
@@ -45,6 +53,35 @@ describe "inputs/kafka", :integration => true do
45
53
  let(:timeout_seconds) { 30 }
46
54
  let(:num_events) { 103 }
47
55
 
56
+ before(:all) do
57
+ # Prepare message with headers with valid UTF-8 chars
58
+ header = org.apache.kafka.common.header.internals.RecordHeader.new("name", "John ανδρεα €".to_java_bytes)
59
+ record = org.apache.kafka.clients.producer.ProducerRecord.new(
60
+ "logstash_integration_topic_plain_with_headers", 0, "key", "value", [header])
61
+ send_message(record)
62
+
63
+ # Prepare message with headers with invalid UTF-8 chars
64
+ invalid = "日本".encode('Shift_JIS').force_encoding(Encoding::UTF_8).to_java_bytes
65
+ header = org.apache.kafka.common.header.internals.RecordHeader.new("name", invalid)
66
+ record = org.apache.kafka.clients.producer.ProducerRecord.new(
67
+ "logstash_integration_topic_plain_with_headers_badly", 0, "key", "value", [header])
68
+
69
+ send_message(record)
70
+ end
71
+
72
+ def send_message(record)
73
+ props = java.util.Properties.new
74
+ kafka = org.apache.kafka.clients.producer.ProducerConfig
75
+ props.put(kafka::BOOTSTRAP_SERVERS_CONFIG, "localhost:9092")
76
+ props.put(kafka::KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer")
77
+ props.put(kafka::VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer")
78
+
79
+ producer = org.apache.kafka.clients.producer.KafkaProducer.new(props)
80
+
81
+ producer.send(record)
82
+ producer.close
83
+ end
84
+
48
85
  describe "#kafka-topics" do
49
86
 
50
87
  it "should consume all messages from plain 3-partition topic" do
@@ -74,7 +111,7 @@ describe "inputs/kafka", :integration => true do
74
111
 
75
112
  context "#kafka-topics-pattern" do
76
113
  it "should consume all messages from all 3 topics" do
77
- total_events = num_events * 3
114
+ total_events = num_events * 3 + 2
78
115
  queue = consume_messages(pattern_config, timeout: timeout_seconds, event_count: total_events)
79
116
  expect(queue.length).to eq(total_events)
80
117
  end
@@ -91,6 +128,31 @@ describe "inputs/kafka", :integration => true do
91
128
  expect(event.get("[@metadata][kafka][timestamp]")).to be >= start
92
129
  end
93
130
  end
131
+
132
+ it "should show the right topic and group name in and kafka headers decorated kafka section" do
133
+ start = LogStash::Timestamp.now.time.to_i
134
+ consume_messages(decorate_headers_config, timeout: timeout_seconds, event_count: 1) do |queue, _|
135
+ expect(queue.length).to eq(1)
136
+ event = queue.shift
137
+ expect(event.get("[@metadata][kafka][topic]")).to eq("logstash_integration_topic_plain_with_headers")
138
+ expect(event.get("[@metadata][kafka][consumer_group]")).to eq(group_id_3)
139
+ expect(event.get("[@metadata][kafka][timestamp]")).to be >= start
140
+ expect(event.get("[@metadata][kafka][headers][name]")).to eq("John ανδρεα €")
141
+ end
142
+ end
143
+
144
+ it "should skip headers not encoded in UTF-8" do
145
+ start = LogStash::Timestamp.now.time.to_i
146
+ consume_messages(decorate_bad_headers_config, timeout: timeout_seconds, event_count: 1) do |queue, _|
147
+ expect(queue.length).to eq(1)
148
+ event = queue.shift
149
+ expect(event.get("[@metadata][kafka][topic]")).to eq("logstash_integration_topic_plain_with_headers_badly")
150
+ expect(event.get("[@metadata][kafka][consumer_group]")).to eq(group_id_3)
151
+ expect(event.get("[@metadata][kafka][timestamp]")).to be >= start
152
+
153
+ expect(event.include?("[@metadata][kafka][headers][name]")).to eq(false)
154
+ end
155
+ end
94
156
  end
95
157
 
96
158
  context "#kafka-offset-commit" do
@@ -129,6 +191,7 @@ private
129
191
 
130
192
  def consume_messages(config, queue: Queue.new, timeout:, event_count:)
131
193
  kafka_input = LogStash::Inputs::Kafka.new(config)
194
+ kafka_input.register
132
195
  t = Thread.new { kafka_input.run(queue) }
133
196
  begin
134
197
  t.run
@@ -38,18 +38,35 @@ describe LogStash::Inputs::Kafka do
38
38
  end
39
39
 
40
40
  context "register parameter verification" do
41
- let(:config) do
42
- { 'schema_registry_url' => 'http://localhost:8081', 'topics' => ['logstash'], 'consumer_threads' => 4 }
43
- end
41
+ context "schema_registry_url" do
42
+ let(:config) do
43
+ { 'schema_registry_url' => 'http://localhost:8081', 'topics' => ['logstash'], 'consumer_threads' => 4 }
44
+ end
44
45
 
45
- it "schema_registry_url conflict with value_deserializer_class should fail" do
46
- config['value_deserializer_class'] = 'my.fantasy.Deserializer'
47
- expect { subject.register }.to raise_error LogStash::ConfigurationError, /Option schema_registry_url prohibit the customization of value_deserializer_class/
46
+ it "conflict with value_deserializer_class should fail" do
47
+ config['value_deserializer_class'] = 'my.fantasy.Deserializer'
48
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Option schema_registry_url prohibit the customization of value_deserializer_class/
49
+ end
50
+
51
+ it "conflict with topics_pattern should fail" do
52
+ config['topics_pattern'] = 'topic_.*'
53
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Option schema_registry_url prohibit the customization of topics_pattern/
54
+ end
48
55
  end
49
56
 
50
- it "schema_registry_url conflict with topics_pattern should fail" do
51
- config['topics_pattern'] = 'topic_.*'
52
- expect { subject.register }.to raise_error LogStash::ConfigurationError, /Option schema_registry_url prohibit the customization of topics_pattern/
57
+ context "decorate_events" do
58
+ let(:config) { { 'decorate_events' => 'extended'} }
59
+
60
+ it "should raise error for invalid value" do
61
+ config['decorate_events'] = 'avoid'
62
+ expect { subject.register }.to raise_error LogStash::ConfigurationError, /Something is wrong with your configuration./
63
+ end
64
+
65
+ it "should map old true boolean value to :record_props mode" do
66
+ config['decorate_events'] = "true"
67
+ subject.register
68
+ expect(subject.metadata_mode).to include(:record_props)
69
+ end
53
70
  end
54
71
  end
55
72
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-integration-kafka
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.7.2
4
+ version: 10.7.3
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-05 00:00:00.000000000 Z
11
+ date: 2021-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -126,6 +126,20 @@ dependencies:
126
126
  - - "<"
127
127
  - !ruby/object:Gem::Version
128
128
  version: 1.0.0
129
+ - !ruby/object:Gem::Dependency
130
+ requirement: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - "~>"
133
+ - !ruby/object:Gem::Version
134
+ version: '1.0'
135
+ name: logstash-mixin-deprecation_logger_support
136
+ prerelease: false
137
+ type: :runtime
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '1.0'
129
143
  - !ruby/object:Gem::Dependency
130
144
  requirement: !ruby/object:Gem::Requirement
131
145
  requirements: