logstash-integration-kafka 10.8.2-java → 10.11.0-java

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e11499f791fd2bd71102ddb6f8e52fcbd9791feecf4107c7ebd27dc9334cc34
4
- data.tar.gz: 779cd381a6e53155f61457229df4fc827ceda02ef4e069d4eab0240dafa4ab83
3
+ metadata.gz: 2833139d65282055a4e924ccfb50b19341a61af69e0834ef318a62f1459f3a16
4
+ data.tar.gz: fbfd7e6b94e9a74109b44b838df344ed4d7447d56d624f24e642235eb62b00e3
5
5
  SHA512:
6
- metadata.gz: 5577048fe1adee0c28b012c0bf6eb0ff594b7be4760f7b7ebdf9072473fb0a1806e24997dd7b0659c21f205396a4d7eccb10bc4e789541c35fb7e32610562632
7
- data.tar.gz: 7ee0e7428d63957a57e927a3f0408bcdddf94efad944c5cf0acbac3c1031be55b6751ad0290ea134e5201f10f9e26f2804c6d68150e925f651c9db27847bab5e
6
+ metadata.gz: b35d99bf553fbfd3b78f3f7de62b427b18001853573c5160090bebba5dfb78f4d17aa9f879a94a98805f949b1ed76a3fa82e9c1a7b95815f223a5d04104f5bce
7
+ data.tar.gz: 0e8edf4f07b00443c39ac55523fb5663395ba0ae524dfedc5181a56b5160c2c33fe110e24bccbb060b43c6be0aa2211b50422d041fa1dea59561a26efc79d687
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 10.11.0
2
+ - Feat: added connections_max_idle_ms setting for output [#118](https://github.com/logstash-plugins/logstash-integration-kafka/pull/118)
3
+ - Refactor: mixins to follow shared mixin module naming
4
+
5
+ ## 10.10.1
6
+ - Update CHANGELOG.md [#114](https://api.github.com/repos/logstash-plugins/logstash-integration-kafka/pulls/114)
7
+
8
+ ## 10.10.0
9
+ - Added config setting to enable 'zstd' compression in the Kafka output [#112](https://github.com/logstash-plugins/logstash-integration-kafka/pull/112)
10
+
11
+ ## 10.9.0
12
+ - Refactor: leverage codec when using schema registry [#106](https://github.com/logstash-plugins/logstash-integration-kafka/pull/106)
13
+ Previously using `schema_registry_url` parsed the payload as JSON even if `codec => 'plain'` was set, this is no longer the case.
14
+
1
15
  ## 10.8.2
2
16
  - [DOC] Updates description of `enable_auto_commit=false` to clarify that the commit happens after data is fetched AND written to the queue [#90](https://github.com/logstash-plugins/logstash-integration-kafka/pull/90)
3
17
  - Fix: update to Gradle 7 [#104](https://github.com/logstash-plugins/logstash-integration-kafka/pull/104)
@@ -82,7 +96,6 @@
82
96
  - Fix links in changelog pointing to stand-alone plugin changelogs.
83
97
  - Refactor: scope java_import to plugin class
84
98
 
85
-
86
99
  ## 10.0.0
87
100
  - Initial release of the Kafka Integration Plugin, which combines
88
101
  previously-separate Kafka plugins and shared dependencies into a single
data/DEVELOPER.md CHANGED
@@ -62,7 +62,7 @@ See http://kafka.apache.org/documentation.html#producerconfigs for details about
62
62
  kafka {
63
63
  topic_id => ... # string (required), The topic to produce the messages to
64
64
  broker_list => ... # string (optional), default: "localhost:9092", This is for bootstrapping and the producer will only use it for getting metadata
65
- compression_codec => ... # string (optional), one of ["none", "gzip", "snappy"], default: "none"
65
+ compression_codec => ... # string (optional), one of ["none", "gzip", "snappy", "lz4", "zstd"], default: "none"
66
66
  compressed_topics => ... # string (optional), default: "", This parameter allows you to set whether compression should be turned on for particular
67
67
  request_required_acks => ... # number (optional), one of [-1, 0, 1], default: 0, This value controls when a produce request is considered completed
68
68
  serializer_class => ... # string, (optional) default: "kafka.serializer.StringEncoder", The serializer class for messages. The default encoder takes a byte[] and returns the same byte[]
@@ -84,7 +84,8 @@ See the https://kafka.apache.org/{kafka_client_doc}/documentation for more detai
84
84
  | <<plugins-{type}s-{plugin}-buffer_memory>> |<<number,number>>|No
85
85
  | <<plugins-{type}s-{plugin}-client_dns_lookup>> |<<string,string>>|No
86
86
  | <<plugins-{type}s-{plugin}-client_id>> |<<string,string>>|No
87
- | <<plugins-{type}s-{plugin}-compression_type>> |<<string,string>>, one of `["none", "gzip", "snappy", "lz4"]`|No
87
+ | <<plugins-{type}s-{plugin}-compression_type>> |<<string,string>>, one of `["none", "gzip", "snappy", "lz4", "zstd"]`|No
88
+ | <<plugins-{type}s-{plugin}-connections_max_idle_ms>> |<<number,number>>|No
88
89
  | <<plugins-{type}s-{plugin}-jaas_path>> |a valid filesystem path|No
89
90
  | <<plugins-{type}s-{plugin}-kerberos_config>> |a valid filesystem path|No
90
91
  | <<plugins-{type}s-{plugin}-key_serializer>> |<<string,string>>|No
@@ -193,11 +194,19 @@ ip/port by allowing a logical application name to be included with the request
193
194
  [id="plugins-{type}s-{plugin}-compression_type"]
194
195
  ===== `compression_type`
195
196
 
196
- * Value can be any of: `none`, `gzip`, `snappy`, `lz4`
197
+ * Value can be any of: `none`, `gzip`, `snappy`, `lz4`, `zstd`
197
198
  * Default value is `"none"`
198
199
 
199
200
  The compression type for all data generated by the producer.
200
- The default is none (i.e. no compression). Valid values are none, gzip, snappy, or lz4.
201
+ The default is none (meaning no compression). Valid values are none, gzip, snappy, lz4, or zstd.
202
+
203
+ [id="plugins-{type}s-{plugin}-connections_max_idle_ms"]
204
+ ===== `connections_max_idle_ms`
205
+
206
+ * Value type is <<number,number>>
207
+ * Default value is `540000` milliseconds (9 minutes).
208
+
209
+ Close idle connections after the number of milliseconds specified by this config.
201
210
 
202
211
  [id="plugins-{type}s-{plugin}-jaas_path"]
203
212
  ===== `jaas_path`
@@ -2,12 +2,11 @@ require 'logstash/namespace'
2
2
  require 'logstash/inputs/base'
3
3
  require 'stud/interval'
4
4
  require 'java'
5
- require 'logstash-integration-kafka_jars.rb'
6
- require 'logstash/plugin_mixins/kafka_support'
7
- require 'manticore'
8
5
  require "json"
9
6
  require "logstash/json"
10
- require_relative '../plugin_mixins/common'
7
+ require 'logstash-integration-kafka_jars.rb'
8
+ require 'logstash/plugin_mixins/kafka/common'
9
+ require 'logstash/plugin_mixins/kafka/avro_schema_registry'
11
10
  require 'logstash/plugin_mixins/deprecation_logger_support'
12
11
 
13
12
  # This input will read events from a Kafka topic. It uses the 0.10 version of
@@ -57,13 +56,18 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
57
56
 
58
57
  DEFAULT_DESERIALIZER_CLASS = "org.apache.kafka.common.serialization.StringDeserializer"
59
58
 
60
- include LogStash::PluginMixins::KafkaSupport
61
- include ::LogStash::PluginMixins::KafkaAvroSchemaRegistry
59
+ include LogStash::PluginMixins::Kafka::Common
60
+ include LogStash::PluginMixins::Kafka::AvroSchemaRegistry
62
61
  include LogStash::PluginMixins::DeprecationLoggerSupport
63
62
 
64
63
  config_name 'kafka'
65
64
 
66
- default :codec, 'plain'
65
+ # default :codec, 'plain' or 'json' depending whether schema registry is used
66
+ #
67
+ # @override LogStash::Inputs::Base - removing the `:default => :plain`
68
+ config :codec, :validate => :codec
69
+ # NOTE: isn't necessary due the params['codec'] = ... done in #initialize
70
+ # having the `nil` default explicit makes the behavior more noticeable.
67
71
 
68
72
  # The frequency in milliseconds that the consumer offsets are committed to Kafka.
69
73
  config :auto_commit_interval_ms, :validate => :number, :default => 5000 # Kafka default
@@ -93,8 +97,6 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
93
97
  # is to be able to track the source of requests beyond just ip/port by allowing
94
98
  # a logical application name to be included.
95
99
  config :client_id, :validate => :string, :default => "logstash"
96
- # Close idle connections after the number of milliseconds specified by this config.
97
- config :connections_max_idle_ms, :validate => :number, :default => 540_000 # (9m) Kafka default
98
100
  # Ideally you should have as many threads as the number of partitions for a perfect
99
101
  # balance — more threads than partitions means that some threads will be idle
100
102
  config :consumer_threads, :validate => :number, :default => 1
@@ -147,9 +149,6 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
147
149
  config :max_partition_fetch_bytes, :validate => :number, :default => 1_048_576 # (1MB) Kafka default
148
150
  # The maximum number of records returned in a single call to poll().
149
151
  config :max_poll_records, :validate => :number, :default => 500 # Kafka default
150
- # The period of time in milliseconds after which we force a refresh of metadata even if
151
- # we haven't seen any partition leadership changes to proactively discover any new brokers or partitions
152
- config :metadata_max_age_ms, :validate => :number, :default => 300_000 # (5m) Kafka default
153
152
  # The name of the partition assignment strategy that the client uses to distribute
154
153
  # partition ownership amongst consumer instances, supported options are `range`,
155
154
  # `round_robin`, `sticky` and `cooperative_sticky`
@@ -162,10 +161,6 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
162
161
  # This avoids repeatedly connecting to a host in a tight loop.
163
162
  # This backoff applies to all connection attempts by the client to a broker.
164
163
  config :reconnect_backoff_ms, :validate => :number, :default => 50 # Kafka default
165
- # The configuration controls the maximum amount of time the client will wait for the response of a request.
166
- # If the response is not received before the timeout elapses the client will resend the request if necessary
167
- # or fail the request if retries are exhausted.
168
- config :request_timeout_ms, :validate => :number, :default => 40_000 # Kafka default
169
164
  # The amount of time to wait before attempting to retry a failed fetch request
170
165
  # to a given topic partition. This avoids repeated fetching-and-failing in a tight loop.
171
166
  config :retry_backoff_ms, :validate => :number, :default => 100 # Kafka default
@@ -249,6 +244,15 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
249
244
 
250
245
  attr_reader :metadata_mode
251
246
 
247
+ # @overload based on schema registry change the codec default
248
+ def initialize(params = {})
249
+ unless params.key?('codec')
250
+ params['codec'] = params.key?('schema_registry_url') ? 'json' : 'plain'
251
+ end
252
+
253
+ super(params)
254
+ end
255
+
252
256
  public
253
257
  def register
254
258
  @runner_threads = []
@@ -341,22 +345,11 @@ class LogStash::Inputs::Kafka < LogStash::Inputs::Base
341
345
  def handle_record(record, codec_instance, queue)
342
346
  codec_instance.decode(record.value.to_s) do |event|
343
347
  decorate(event)
344
- maybe_apply_schema(event, record)
345
348
  maybe_set_metadata(event, record)
346
349
  queue << event
347
350
  end
348
351
  end
349
352
 
350
- def maybe_apply_schema(event, record)
351
- if schema_registry_url
352
- json = LogStash::Json.load(record.value.to_s)
353
- json.each do |k, v|
354
- event.set(k, v)
355
- end
356
- event.remove("message")
357
- end
358
- end
359
-
360
353
  def maybe_set_metadata(event, record)
361
354
  if @metadata_mode.include?(:record_props)
362
355
  event.set("[@metadata][kafka][topic]", record.topic)
@@ -2,7 +2,7 @@ require 'logstash/namespace'
2
2
  require 'logstash/outputs/base'
3
3
  require 'java'
4
4
  require 'logstash-integration-kafka_jars.rb'
5
- require 'logstash/plugin_mixins/kafka_support'
5
+ require 'logstash/plugin_mixins/kafka/common'
6
6
 
7
7
  # Write events to a Kafka topic. This uses the Kafka Producer API to write messages to a topic on
8
8
  # the broker.
@@ -51,7 +51,7 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base
51
51
 
52
52
  java_import org.apache.kafka.clients.producer.ProducerRecord
53
53
 
54
- include LogStash::PluginMixins::KafkaSupport
54
+ include LogStash::PluginMixins::Kafka::Common
55
55
 
56
56
  declare_threadsafe!
57
57
 
@@ -80,8 +80,8 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base
80
80
  # The total bytes of memory the producer can use to buffer records waiting to be sent to the server.
81
81
  config :buffer_memory, :validate => :number, :default => 33_554_432 # (32M) Kafka default
82
82
  # The compression type for all data generated by the producer.
83
- # The default is none (i.e. no compression). Valid values are none, gzip, or snappy.
84
- config :compression_type, :validate => ["none", "gzip", "snappy", "lz4"], :default => "none"
83
+ # The default is none (i.e. no compression). Valid values are none, gzip, snappy, lz4 or zstd.
84
+ config :compression_type, :validate => ["none", "gzip", "snappy", "lz4", "zstd"], :default => "none"
85
85
  # How DNS lookups should be done. If set to `use_all_dns_ips`, when the lookup returns multiple
86
86
  # IP addresses for a hostname, they will all be attempted to connect to before failing the
87
87
  # connection. If the value is `resolve_canonical_bootstrap_servers_only` each entry will be
@@ -107,19 +107,12 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base
107
107
  config :message_key, :validate => :string
108
108
  # the timeout setting for initial metadata request to fetch topic metadata.
109
109
  config :metadata_fetch_timeout_ms, :validate => :number, :default => 60_000
110
- # the max time in milliseconds before a metadata refresh is forced.
111
- config :metadata_max_age_ms, :validate => :number, :default => 300_000 # (5m) Kafka default
112
110
  # Partitioner to use - can be `default`, `uniform_sticky`, `round_robin` or a fully qualified class name of a custom partitioner.
113
111
  config :partitioner, :validate => :string
114
112
  # The size of the TCP receive buffer to use when reading data
115
113
  config :receive_buffer_bytes, :validate => :number, :default => 32_768 # (32KB) Kafka default
116
114
  # The amount of time to wait before attempting to reconnect to a given host when a connection fails.
117
115
  config :reconnect_backoff_ms, :validate => :number, :default => 50 # Kafka default
118
- # The configuration controls the maximum amount of time the client will wait
119
- # for the response of a request. If the response is not received before the timeout
120
- # elapses the client will resend the request if necessary or fail the request if
121
- # retries are exhausted.
122
- config :request_timeout_ms, :validate => :number, :default => 40_000 # (40s) Kafka default
123
116
  # The default retry behavior is to retry until successful. To prevent data loss,
124
117
  # the use of this setting is discouraged.
125
118
  #
@@ -0,0 +1,108 @@
1
+ require 'manticore'
2
+
3
+ module LogStash module PluginMixins module Kafka
4
+ module AvroSchemaRegistry
5
+
6
+ def self.included(base)
7
+ base.extend(self)
8
+ base.setup_schema_registry_config
9
+ end
10
+
11
+ def setup_schema_registry_config
12
+ # Option to set key to access Schema Registry.
13
+ config :schema_registry_key, :validate => :string
14
+
15
+ # Option to set secret to access Schema Registry.
16
+ config :schema_registry_secret, :validate => :password
17
+
18
+ # Option to set the endpoint of the Schema Registry.
19
+ # This option permit the usage of Avro Kafka deserializer which retrieve the schema of the Avro message from an
20
+ # instance of schema registry. If this option has value `value_deserializer_class` nor `topics_pattern` could be valued
21
+ config :schema_registry_url, :validate => :uri
22
+
23
+ # Option to set the proxy of the Schema Registry.
24
+ # This option permits to define a proxy to be used to reach the schema registry service instance.
25
+ config :schema_registry_proxy, :validate => :uri
26
+
27
+ # Option to skip validating the schema registry during registration. This can be useful when using
28
+ # certificate based auth
29
+ config :schema_registry_validation, :validate => ['auto', 'skip'], :default => 'auto'
30
+ end
31
+
32
+ def check_schema_registry_parameters
33
+ if @schema_registry_url
34
+ check_for_schema_registry_conflicts
35
+ @schema_registry_proxy_host, @schema_registry_proxy_port = split_proxy_into_host_and_port(schema_registry_proxy)
36
+ check_for_key_and_secret
37
+ check_for_schema_registry_connectivity_and_subjects if schema_registry_validation?
38
+ end
39
+ end
40
+
41
+ def schema_registry_validation?
42
+ return false if schema_registry_validation.to_s == 'skip'
43
+ return false if using_kerberos? # pre-validation doesn't support kerberos
44
+
45
+ true
46
+ end
47
+
48
+ def using_kerberos?
49
+ security_protocol == "SASL_PLAINTEXT" || security_protocol == "SASL_SSL"
50
+ end
51
+
52
+ private
53
+ def check_for_schema_registry_conflicts
54
+ if @value_deserializer_class != LogStash::Inputs::Kafka::DEFAULT_DESERIALIZER_CLASS
55
+ raise LogStash::ConfigurationError, 'Option schema_registry_url prohibit the customization of value_deserializer_class'
56
+ end
57
+ if @topics_pattern && !@topics_pattern.empty?
58
+ raise LogStash::ConfigurationError, 'Option schema_registry_url prohibit the customization of topics_pattern'
59
+ end
60
+ end
61
+
62
+ private
63
+ def check_for_schema_registry_connectivity_and_subjects
64
+ options = {}
65
+ if schema_registry_proxy && !schema_registry_proxy.empty?
66
+ options[:proxy] = schema_registry_proxy.to_s
67
+ end
68
+ if schema_registry_key and !schema_registry_key.empty?
69
+ options[:auth] = {:user => schema_registry_key, :password => schema_registry_secret.value}
70
+ end
71
+ client = Manticore::Client.new(options)
72
+ begin
73
+ response = client.get(@schema_registry_url.uri.to_s + '/subjects').body
74
+ rescue Manticore::ManticoreException => e
75
+ raise LogStash::ConfigurationError.new("Schema registry service doesn't respond, error: #{e.message}")
76
+ end
77
+ registered_subjects = JSON.parse response
78
+ expected_subjects = @topics.map { |t| "#{t}-value"}
79
+ if (expected_subjects & registered_subjects).size != expected_subjects.size
80
+ undefined_topic_subjects = expected_subjects - registered_subjects
81
+ raise LogStash::ConfigurationError, "The schema registry does not contain definitions for required topic subjects: #{undefined_topic_subjects}"
82
+ end
83
+ end
84
+
85
+ def split_proxy_into_host_and_port(proxy_uri)
86
+ return nil unless proxy_uri && !proxy_uri.empty?
87
+
88
+ port = proxy_uri.port
89
+
90
+ host_spec = ""
91
+ host_spec << proxy_uri.scheme || "http"
92
+ host_spec << "://"
93
+ host_spec << "#{proxy_uri.userinfo}@" if proxy_uri.userinfo
94
+ host_spec << proxy_uri.host
95
+
96
+ [host_spec, port]
97
+ end
98
+
99
+ def check_for_key_and_secret
100
+ if schema_registry_key and !schema_registry_key.empty?
101
+ if !schema_registry_secret or schema_registry_secret.value.empty?
102
+ raise LogStash::ConfigurationError, "Setting `schema_registry_secret` is required when `schema_registry_key` is provided."
103
+ end
104
+ end
105
+ end
106
+
107
+ end
108
+ end end end
@@ -0,0 +1,47 @@
1
+ module LogStash module PluginMixins module Kafka
2
+ module Common
3
+
4
+ def self.included(base)
5
+ # COMMON CONFIGURATION SUPPORTED BY BOTH PRODUCER/CONSUMER
6
+
7
+ # Close idle connections after the number of milliseconds specified by this config.
8
+ base.config :connections_max_idle_ms, :validate => :number, :default => 540_000 # (9m) Kafka default
9
+
10
+ # The period of time in milliseconds after which we force a refresh of metadata even if
11
+ # we haven't seen any partition leadership changes to proactively discover any new brokers or partitions
12
+ base.config :metadata_max_age_ms, :validate => :number, :default => 300_000 # (5m) Kafka default
13
+
14
+ # The configuration controls the maximum amount of time the client will wait for the response of a request.
15
+ # If the response is not received before the timeout elapses the client will resend the request if necessary
16
+ # or fail the request if retries are exhausted.
17
+ base.config :request_timeout_ms, :validate => :number, :default => 40_000 # Kafka default
18
+ end
19
+
20
+ def set_trustore_keystore_config(props)
21
+ props.put("ssl.truststore.type", ssl_truststore_type) unless ssl_truststore_type.nil?
22
+ props.put("ssl.truststore.location", ssl_truststore_location) unless ssl_truststore_location.nil?
23
+ props.put("ssl.truststore.password", ssl_truststore_password.value) unless ssl_truststore_password.nil?
24
+
25
+ # Client auth stuff
26
+ props.put("ssl.keystore.type", ssl_keystore_type) unless ssl_keystore_type.nil?
27
+ props.put("ssl.key.password", ssl_key_password.value) unless ssl_key_password.nil?
28
+ props.put("ssl.keystore.location", ssl_keystore_location) unless ssl_keystore_location.nil?
29
+ props.put("ssl.keystore.password", ssl_keystore_password.value) unless ssl_keystore_password.nil?
30
+ props.put("ssl.endpoint.identification.algorithm", ssl_endpoint_identification_algorithm) unless ssl_endpoint_identification_algorithm.nil?
31
+ end
32
+
33
+ def set_sasl_config(props)
34
+ java.lang.System.setProperty("java.security.auth.login.config", jaas_path) unless jaas_path.nil?
35
+ java.lang.System.setProperty("java.security.krb5.conf", kerberos_config) unless kerberos_config.nil?
36
+
37
+ props.put("sasl.mechanism", sasl_mechanism)
38
+ if sasl_mechanism == "GSSAPI" && sasl_kerberos_service_name.nil?
39
+ raise LogStash::ConfigurationError, "sasl_kerberos_service_name must be specified when SASL mechanism is GSSAPI"
40
+ end
41
+
42
+ props.put("sasl.kerberos.service.name", sasl_kerberos_service_name) unless sasl_kerberos_service_name.nil?
43
+ props.put("sasl.jaas.config", sasl_jaas_config) unless sasl_jaas_config.nil?
44
+ end
45
+
46
+ end
47
+ end end end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-integration-kafka'
3
- s.version = '10.8.2'
3
+ s.version = '10.11.0'
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 "+
@@ -50,6 +50,7 @@ Gem::Specification.new do |s|
50
50
  s.add_runtime_dependency 'logstash-mixin-deprecation_logger_support', '~>1.0'
51
51
 
52
52
  s.add_development_dependency 'logstash-devutils'
53
+ s.add_development_dependency 'logstash-codec-line'
53
54
  s.add_development_dependency 'rspec-wait'
54
55
  s.add_development_dependency 'digest-crc', '~> 0.5.1' # 0.6.0 started using a C-ext
55
56
  s.add_development_dependency 'ruby-kafka' # depends on digest-crc
@@ -16,38 +16,38 @@ describe "inputs/kafka", :integration => true do
16
16
  let(:group_id_5) {rand(36**8).to_s(36)}
17
17
  let(:group_id_6) {rand(36**8).to_s(36)}
18
18
  let(:plain_config) do
19
- { 'topics' => ['logstash_integration_topic_plain'], 'codec' => 'plain', 'group_id' => group_id_1,
19
+ { 'topics' => ['logstash_integration_topic_plain'], 'group_id' => group_id_1,
20
20
  'auto_offset_reset' => 'earliest' }
21
21
  end
22
22
  let(:multi_consumer_config) do
23
23
  plain_config.merge({"group_id" => group_id_4, "client_id" => "spec", "consumer_threads" => 3})
24
24
  end
25
25
  let(:snappy_config) do
26
- { 'topics' => ['logstash_integration_topic_snappy'], 'codec' => 'plain', 'group_id' => group_id_1,
26
+ { 'topics' => ['logstash_integration_topic_snappy'], 'group_id' => group_id_1,
27
27
  'auto_offset_reset' => 'earliest' }
28
28
  end
29
29
  let(:lz4_config) do
30
- { 'topics' => ['logstash_integration_topic_lz4'], 'codec' => 'plain', 'group_id' => group_id_1,
30
+ { 'topics' => ['logstash_integration_topic_lz4'], 'group_id' => group_id_1,
31
31
  'auto_offset_reset' => 'earliest' }
32
32
  end
33
33
  let(:pattern_config) do
34
- { 'topics_pattern' => 'logstash_integration_topic_.*', 'group_id' => group_id_2, 'codec' => 'plain',
34
+ { 'topics_pattern' => 'logstash_integration_topic_.*', 'group_id' => group_id_2,
35
35
  'auto_offset_reset' => 'earliest' }
36
36
  end
37
37
  let(:decorate_config) do
38
- { 'topics' => ['logstash_integration_topic_plain'], 'codec' => 'plain', 'group_id' => group_id_3,
38
+ { 'topics' => ['logstash_integration_topic_plain'], 'group_id' => group_id_3,
39
39
  'auto_offset_reset' => 'earliest', 'decorate_events' => 'true' }
40
40
  end
41
41
  let(:decorate_headers_config) do
42
- { 'topics' => ['logstash_integration_topic_plain_with_headers'], 'codec' => 'plain', 'group_id' => group_id_3,
42
+ { 'topics' => ['logstash_integration_topic_plain_with_headers'], 'group_id' => group_id_3,
43
43
  'auto_offset_reset' => 'earliest', 'decorate_events' => 'extended' }
44
44
  end
45
45
  let(:decorate_bad_headers_config) do
46
- { 'topics' => ['logstash_integration_topic_plain_with_headers_badly'], 'codec' => 'plain', 'group_id' => group_id_3,
46
+ { 'topics' => ['logstash_integration_topic_plain_with_headers_badly'], 'group_id' => group_id_3,
47
47
  'auto_offset_reset' => 'earliest', 'decorate_events' => 'extended' }
48
48
  end
49
49
  let(:manual_commit_config) do
50
- { 'topics' => ['logstash_integration_topic_plain'], 'codec' => 'plain', 'group_id' => group_id_5,
50
+ { 'topics' => ['logstash_integration_topic_plain'], 'group_id' => group_id_5,
51
51
  'auto_offset_reset' => 'earliest', 'enable_auto_commit' => 'false' }
52
52
  end
53
53
  let(:timeout_seconds) { 30 }
@@ -352,10 +352,7 @@ describe "Deserializing with the schema registry", :integration => true do
352
352
 
353
353
  let(:base_config) do
354
354
  {
355
- 'topics' => [avro_topic_name],
356
- 'codec' => 'plain',
357
- 'group_id' => group_id_1,
358
- 'auto_offset_reset' => 'earliest'
355
+ 'topics' => [avro_topic_name], 'group_id' => group_id_1, 'auto_offset_reset' => 'earliest'
359
356
  }
360
357
  end
361
358
 
@@ -28,7 +28,8 @@ describe "outputs/kafka", :integration => true do
28
28
  let(:num_events) { 3 }
29
29
 
30
30
  before :each do
31
- config = base_config.merge({"topic_id" => test_topic})
31
+ # NOTE: the connections_max_idle_ms is irrelevant just testing that configuration works ...
32
+ config = base_config.merge({"topic_id" => test_topic, "connections_max_idle_ms" => 540_000})
32
33
  load_kafka_data(config)
33
34
  end
34
35
 
@@ -139,6 +140,25 @@ describe "outputs/kafka", :integration => true do
139
140
  # end
140
141
  end
141
142
 
143
+ context 'when using zstd compression' do
144
+ let(:test_topic) { 'logstash_integration_zstd_topic' }
145
+
146
+ before :each do
147
+ config = base_config.merge({"topic_id" => test_topic, "compression_type" => "zstd"})
148
+ load_kafka_data(config)
149
+ end
150
+
151
+ # NOTE: depends on zstd-ruby gem which is using a C-extension
152
+ # it 'should have data integrity' do
153
+ # messages = fetch_messages(test_topic)
154
+ #
155
+ # expect(messages.size).to eq(num_events)
156
+ # messages.each do |m|
157
+ # expect(m.value).to eq(event.to_s)
158
+ # end
159
+ # end
160
+ end
161
+
142
162
  context 'when using multi partition topic' do
143
163
  let(:num_events) { 100 } # ~ more than (batch.size) 16,384 bytes
144
164
  let(:test_topic) { 'logstash_integration_topic3' }
@@ -177,7 +177,23 @@ describe LogStash::Inputs::Kafka do
177
177
  end
178
178
  end
179
179
 
180
- describe "schema registry parameter verification" do
180
+ it 'uses plain codec by default' do
181
+ expect( subject.codec ).to respond_to :decode
182
+ expect( subject.codec.class ).to be LogStash::Codecs::Plain
183
+ end
184
+
185
+ context 'with codec option' do
186
+
187
+ let(:config) { super().merge 'codec' => 'line' }
188
+
189
+ it 'uses specified codec' do
190
+ expect( subject.codec ).to respond_to :decode
191
+ expect( subject.codec.class ).to be LogStash::Codecs::Line
192
+ end
193
+
194
+ end
195
+
196
+ describe "schema registry" do
181
197
  let(:base_config) do {
182
198
  'schema_registry_url' => 'http://localhost:8081',
183
199
  'topics' => ['logstash'],
@@ -186,7 +202,7 @@ describe LogStash::Inputs::Kafka do
186
202
  end
187
203
 
188
204
  context "schema_registry_url" do
189
- let(:config) { base_config }
205
+ let(:config) { base_config }
190
206
 
191
207
  it "conflict with value_deserializer_class should fail" do
192
208
  config['value_deserializer_class'] = 'my.fantasy.Deserializer'
@@ -197,6 +213,11 @@ describe LogStash::Inputs::Kafka do
197
213
  config['topics_pattern'] = 'topic_.*'
198
214
  expect { subject.register }.to raise_error LogStash::ConfigurationError, /Option schema_registry_url prohibit the customization of topics_pattern/
199
215
  end
216
+
217
+ it 'switches default codec to json' do
218
+ expect( subject.codec ).to respond_to :decode
219
+ expect( subject.codec.class ).to be LogStash::Codecs::JSON
220
+ end
200
221
  end
201
222
 
202
223
  context 'when kerberos auth is used' do
@@ -204,9 +225,8 @@ describe LogStash::Inputs::Kafka do
204
225
  context "with #{protocol}" do
205
226
  ['auto', 'skip'].each do |vsr|
206
227
  context "when validata_schema_registry is #{vsr}" do
207
- let(:config) { base_config.merge({'security_protocol' => protocol,
208
- 'schema_registry_validation' => vsr})
209
- }
228
+ let(:config) { base_config.merge({'security_protocol' => protocol, 'schema_registry_validation' => vsr}) }
229
+
210
230
  it 'skips verification' do
211
231
  expect(subject).not_to receive(:check_for_schema_registry_connectivity_and_subjects)
212
232
  expect { subject.register }.not_to raise_error
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.8.2
4
+ version: 10.11.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-04 00:00:00.000000000 Z
11
+ date: 2022-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -154,6 +154,20 @@ dependencies:
154
154
  - - ">="
155
155
  - !ruby/object:Gem::Version
156
156
  version: '0'
157
+ - !ruby/object:Gem::Dependency
158
+ requirement: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ name: logstash-codec-line
164
+ prerelease: false
165
+ type: :development
166
+ version_requirements: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
157
171
  - !ruby/object:Gem::Dependency
158
172
  requirement: !ruby/object:Gem::Requirement
159
173
  requirements:
@@ -231,8 +245,8 @@ files:
231
245
  - lib/logstash-integration-kafka_jars.rb
232
246
  - lib/logstash/inputs/kafka.rb
233
247
  - lib/logstash/outputs/kafka.rb
234
- - lib/logstash/plugin_mixins/common.rb
235
- - lib/logstash/plugin_mixins/kafka_support.rb
248
+ - lib/logstash/plugin_mixins/kafka/avro_schema_registry.rb
249
+ - lib/logstash/plugin_mixins/kafka/common.rb
236
250
  - logstash-integration-kafka.gemspec
237
251
  - spec/check_docs_spec.rb
238
252
  - spec/fixtures/jaas.config
@@ -1,107 +0,0 @@
1
- module LogStash
2
- module PluginMixins
3
- module KafkaAvroSchemaRegistry
4
-
5
- def self.included(base)
6
- base.extend(self)
7
- base.setup_schema_registry_config
8
- end
9
-
10
- def setup_schema_registry_config
11
- # Option to set key to access Schema Registry.
12
- config :schema_registry_key, :validate => :string
13
-
14
- # Option to set secret to access Schema Registry.
15
- config :schema_registry_secret, :validate => :password
16
-
17
- # Option to set the endpoint of the Schema Registry.
18
- # This option permit the usage of Avro Kafka deserializer which retrieve the schema of the Avro message from an
19
- # instance of schema registry. If this option has value `value_deserializer_class` nor `topics_pattern` could be valued
20
- config :schema_registry_url, :validate => :uri
21
-
22
- # Option to set the proxy of the Schema Registry.
23
- # This option permits to define a proxy to be used to reach the schema registry service instance.
24
- config :schema_registry_proxy, :validate => :uri
25
-
26
- # Option to skip validating the schema registry during registration. This can be useful when using
27
- # certificate based auth
28
- config :schema_registry_validation, :validate => ['auto', 'skip'], :default => 'auto'
29
- end
30
-
31
- def check_schema_registry_parameters
32
- if @schema_registry_url
33
- check_for_schema_registry_conflicts
34
- @schema_registry_proxy_host, @schema_registry_proxy_port = split_proxy_into_host_and_port(schema_registry_proxy)
35
- check_for_key_and_secret
36
- check_for_schema_registry_connectivity_and_subjects if schema_registry_validation?
37
- end
38
- end
39
-
40
- def schema_registry_validation?
41
- return false if schema_registry_validation.to_s == 'skip'
42
- return false if using_kerberos? # pre-validation doesn't support kerberos
43
-
44
- true
45
- end
46
-
47
- def using_kerberos?
48
- security_protocol == "SASL_PLAINTEXT" || security_protocol == "SASL_SSL"
49
- end
50
-
51
- private
52
- def check_for_schema_registry_conflicts
53
- if @value_deserializer_class != LogStash::Inputs::Kafka::DEFAULT_DESERIALIZER_CLASS
54
- raise LogStash::ConfigurationError, 'Option schema_registry_url prohibit the customization of value_deserializer_class'
55
- end
56
- if @topics_pattern && !@topics_pattern.empty?
57
- raise LogStash::ConfigurationError, 'Option schema_registry_url prohibit the customization of topics_pattern'
58
- end
59
- end
60
-
61
- private
62
- def check_for_schema_registry_connectivity_and_subjects
63
- options = {}
64
- if schema_registry_proxy && !schema_registry_proxy.empty?
65
- options[:proxy] = schema_registry_proxy.to_s
66
- end
67
- if schema_registry_key and !schema_registry_key.empty?
68
- options[:auth] = {:user => schema_registry_key, :password => schema_registry_secret.value}
69
- end
70
- client = Manticore::Client.new(options)
71
- begin
72
- response = client.get(@schema_registry_url.uri.to_s + '/subjects').body
73
- rescue Manticore::ManticoreException => e
74
- raise LogStash::ConfigurationError.new("Schema registry service doesn't respond, error: #{e.message}")
75
- end
76
- registered_subjects = JSON.parse response
77
- expected_subjects = @topics.map { |t| "#{t}-value"}
78
- if (expected_subjects & registered_subjects).size != expected_subjects.size
79
- undefined_topic_subjects = expected_subjects - registered_subjects
80
- raise LogStash::ConfigurationError, "The schema registry does not contain definitions for required topic subjects: #{undefined_topic_subjects}"
81
- end
82
- end
83
-
84
- def split_proxy_into_host_and_port(proxy_uri)
85
- return nil unless proxy_uri && !proxy_uri.empty?
86
-
87
- port = proxy_uri.port
88
-
89
- host_spec = ""
90
- host_spec << proxy_uri.scheme || "http"
91
- host_spec << "://"
92
- host_spec << "#{proxy_uri.userinfo}@" if proxy_uri.userinfo
93
- host_spec << proxy_uri.host
94
-
95
- [host_spec, port]
96
- end
97
-
98
- def check_for_key_and_secret
99
- if schema_registry_key and !schema_registry_key.empty?
100
- if !schema_registry_secret or schema_registry_secret.value.empty?
101
- raise LogStash::ConfigurationError, "Setting `schema_registry_secret` is required when `schema_registry_key` is provided."
102
- end
103
- end
104
- end
105
- end
106
- end
107
- end
@@ -1,29 +0,0 @@
1
- module LogStash module PluginMixins module KafkaSupport
2
-
3
- def set_trustore_keystore_config(props)
4
- props.put("ssl.truststore.type", ssl_truststore_type) unless ssl_truststore_type.nil?
5
- props.put("ssl.truststore.location", ssl_truststore_location) unless ssl_truststore_location.nil?
6
- props.put("ssl.truststore.password", ssl_truststore_password.value) unless ssl_truststore_password.nil?
7
-
8
- # Client auth stuff
9
- props.put("ssl.keystore.type", ssl_keystore_type) unless ssl_keystore_type.nil?
10
- props.put("ssl.key.password", ssl_key_password.value) unless ssl_key_password.nil?
11
- props.put("ssl.keystore.location", ssl_keystore_location) unless ssl_keystore_location.nil?
12
- props.put("ssl.keystore.password", ssl_keystore_password.value) unless ssl_keystore_password.nil?
13
- props.put("ssl.endpoint.identification.algorithm", ssl_endpoint_identification_algorithm) unless ssl_endpoint_identification_algorithm.nil?
14
- end
15
-
16
- def set_sasl_config(props)
17
- java.lang.System.setProperty("java.security.auth.login.config", jaas_path) unless jaas_path.nil?
18
- java.lang.System.setProperty("java.security.krb5.conf", kerberos_config) unless kerberos_config.nil?
19
-
20
- props.put("sasl.mechanism", sasl_mechanism)
21
- if sasl_mechanism == "GSSAPI" && sasl_kerberos_service_name.nil?
22
- raise LogStash::ConfigurationError, "sasl_kerberos_service_name must be specified when SASL mechanism is GSSAPI"
23
- end
24
-
25
- props.put("sasl.kerberos.service.name", sasl_kerberos_service_name) unless sasl_kerberos_service_name.nil?
26
- props.put("sasl.jaas.config", sasl_jaas_config) unless sasl_jaas_config.nil?
27
- end
28
-
29
- end end end