logstash-output-kafka 7.0.1 → 7.0.3
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 +4 -4
- data/CHANGELOG.md +10 -0
- data/docs/index.asciidoc +17 -10
- data/lib/logstash/outputs/kafka.rb +103 -11
- data/logstash-output-kafka.gemspec +1 -1
- data/spec/integration/outputs/kafka_spec.rb +1 -1
- data/spec/unit/outputs/kafka_spec.rb +93 -9
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: a5ccedfbfedaaf72bad1ec4696411dd1859e1922
         | 
| 4 | 
            +
              data.tar.gz: c4180be5c8a6e66d49b421ebf46e962948c03c35
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3fe5acfc009c895074de3d3c84fc188c5bbaba6297f5a0b1c2286fbd25da7688f6f56ad28d9f60c5c4d6ac01ba0bafccb4e5bdccc5b960e8d0c934c21a5312b9
         | 
| 7 | 
            +
              data.tar.gz: 4916c1b9c9aac493d83e63a5448b3776603ec2f4dbcaca58e37850e8a19a8e8a0acb8de7e68b6c61a6fc5304c8ad2a92b0b6dce1f48fff8e1cf4d3da3e3abdf1
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,13 @@ | |
| 1 | 
            +
            ## 7.0.3
         | 
| 2 | 
            +
              - Bugfix: Sends are now retried until successful. Previously, failed transmissions to Kafka
         | 
| 3 | 
            +
                could have been lost by the KafkaProducer library. Now we verify transmission explicitly.
         | 
| 4 | 
            +
                This changes the default 'retry' from 0 to retry-forever. It was a bug that we defaulted
         | 
| 5 | 
            +
                to a retry count of 0.
         | 
| 6 | 
            +
                https://github.com/logstash-plugins/logstash-output-kafka/pull/151
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ## 7.0.2
         | 
| 9 | 
            +
              - Docs: Fix misleading info about the default codec
         | 
| 10 | 
            +
             | 
| 1 11 | 
             
            ## 7.0.1
         | 
| 2 12 | 
             
              - Fix some documentation issues
         | 
| 3 13 |  | 
    
        data/docs/index.asciidoc
    CHANGED
    
    | @@ -48,19 +48,19 @@ This output supports connecting to Kafka over: | |
| 48 48 |  | 
| 49 49 | 
             
            By default security is disabled but can be turned on as needed.
         | 
| 50 50 |  | 
| 51 | 
            -
            The only required configuration is the topic_id.  | 
| 52 | 
            -
             | 
| 53 | 
            -
            only the message but also with a timestamp and hostname. | 
| 54 | 
            -
             | 
| 51 | 
            +
            The only required configuration is the topic_id. 
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            The default codec is plain. Logstash will encode your events with not only the message field but also with a timestamp and hostname.
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            If you want the full content of your events to be sent as json, you should set the codec in the output configuration like this:
         | 
| 55 56 | 
             
            [source,ruby]
         | 
| 56 57 | 
             
                output {
         | 
| 57 58 | 
             
                  kafka {
         | 
| 58 | 
            -
                    codec =>  | 
| 59 | 
            -
                       format => "%{message}"
         | 
| 60 | 
            -
                    }
         | 
| 59 | 
            +
                    codec => json
         | 
| 61 60 | 
             
                    topic_id => "mytopic"
         | 
| 62 61 | 
             
                  }
         | 
| 63 62 | 
             
                }
         | 
| 63 | 
            +
                
         | 
| 64 64 | 
             
            For more information see http://kafka.apache.org/documentation.html#theproducer
         | 
| 65 65 |  | 
| 66 66 | 
             
            Kafka producer configuration: http://kafka.apache.org/documentation.html#newproducerconfigs
         | 
| @@ -291,10 +291,17 @@ retries are exhausted. | |
| 291 291 | 
             
            ===== `retries` 
         | 
| 292 292 |  | 
| 293 293 | 
             
              * Value type is <<number,number>>
         | 
| 294 | 
            -
              *  | 
| 294 | 
            +
              * There is no default value for this setting.
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            The default retry behavior is to retry until successful. To prevent data loss,
         | 
| 297 | 
            +
            the use of this setting is discouraged.
         | 
| 298 | 
            +
             | 
| 299 | 
            +
            If you choose to set `retries`, a value greater than zero will cause the
         | 
| 300 | 
            +
            client to only retry a fixed number of times. This will result in data loss
         | 
| 301 | 
            +
            if a transport fault exists for longer than your retry count (network outage,
         | 
| 302 | 
            +
            Kafka down, etc).
         | 
| 295 303 |  | 
| 296 | 
            -
             | 
| 297 | 
            -
            resend any record whose send fails with a potentially transient error.
         | 
| 304 | 
            +
            A value less than zero is a configuration error.
         | 
| 298 305 |  | 
| 299 306 | 
             
            [id="plugins-{type}s-{plugin}-retry_backoff_ms"]
         | 
| 300 307 | 
             
            ===== `retry_backoff_ms` 
         | 
| @@ -109,9 +109,15 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base | |
| 109 109 | 
             
              # elapses the client will resend the request if necessary or fail the request if
         | 
| 110 110 | 
             
              # retries are exhausted.
         | 
| 111 111 | 
             
              config :request_timeout_ms, :validate => :string
         | 
| 112 | 
            -
              #  | 
| 113 | 
            -
              #  | 
| 114 | 
            -
               | 
| 112 | 
            +
              # The default retry behavior is to retry until successful. To prevent data loss,
         | 
| 113 | 
            +
              # the use of this setting is discouraged.
         | 
| 114 | 
            +
              #
         | 
| 115 | 
            +
              # If you choose to set `retries`, a value greater than zero will cause the
         | 
| 116 | 
            +
              # client to only retry a fixed number of times. This will result in data loss
         | 
| 117 | 
            +
              # if a transient error outlasts your retry count.
         | 
| 118 | 
            +
              #
         | 
| 119 | 
            +
              # A value less than zero is a configuration error.
         | 
| 120 | 
            +
              config :retries, :validate => :number
         | 
| 115 121 | 
             
              # The amount of time to wait before attempting to retry a failed produce request to a given topic partition.
         | 
| 116 122 | 
             
              config :retry_backoff_ms, :validate => :number, :default => 100
         | 
| 117 123 | 
             
              # The size of the TCP send buffer to use when sending data.
         | 
| @@ -170,6 +176,17 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base | |
| 170 176 |  | 
| 171 177 | 
             
              public
         | 
| 172 178 | 
             
              def register
         | 
| 179 | 
            +
                @thread_batch_map = Concurrent::Hash.new
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                if !@retries.nil? 
         | 
| 182 | 
            +
                  if @retries < 0
         | 
| 183 | 
            +
                    raise ConfigurationError, "A negative retry count (#{@retries}) is not valid. Must be a value >= 0"
         | 
| 184 | 
            +
                  end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                  @logger.warn("Kafka output is configured with finite retry. This instructs Logstash to LOSE DATA after a set number of send attempts fails. If you do not want to lose data if Kafka is down, then you must remove the retry setting.", :retries => @retries)
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
             | 
| 189 | 
            +
             | 
| 173 190 | 
             
                @producer = create_producer
         | 
| 174 191 | 
             
                @codec.on_event do |event, data|
         | 
| 175 192 | 
             
                  begin
         | 
| @@ -178,7 +195,7 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base | |
| 178 195 | 
             
                    else
         | 
| 179 196 | 
             
                      record = org.apache.kafka.clients.producer.ProducerRecord.new(event.sprintf(@topic_id), event.sprintf(@message_key), data)
         | 
| 180 197 | 
             
                    end
         | 
| 181 | 
            -
                     | 
| 198 | 
            +
                    prepare(record)
         | 
| 182 199 | 
             
                  rescue LogStash::ShutdownSignal
         | 
| 183 200 | 
             
                    @logger.debug('Kafka producer got shutdown signal')
         | 
| 184 201 | 
             
                  rescue => e
         | 
| @@ -186,14 +203,89 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base | |
| 186 203 | 
             
                                 :exception => e)
         | 
| 187 204 | 
             
                  end
         | 
| 188 205 | 
             
                end
         | 
| 189 | 
            -
             | 
| 190 206 | 
             
              end # def register
         | 
| 191 207 |  | 
| 192 | 
            -
              def  | 
| 193 | 
            -
                 | 
| 194 | 
            -
             | 
| 208 | 
            +
              def prepare(record)
         | 
| 209 | 
            +
                # This output is threadsafe, so we need to keep a batch per thread.
         | 
| 210 | 
            +
                @thread_batch_map[Thread.current].add(record)
         | 
| 211 | 
            +
              end
         | 
| 212 | 
            +
             | 
| 213 | 
            +
              def multi_receive(events)
         | 
| 214 | 
            +
                t = Thread.current
         | 
| 215 | 
            +
                if !@thread_batch_map.include?(t)
         | 
| 216 | 
            +
                  @thread_batch_map[t] = java.util.ArrayList.new(events.size)
         | 
| 217 | 
            +
                end
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                events.each do |event|
         | 
| 220 | 
            +
                  break if event == LogStash::SHUTDOWN
         | 
| 221 | 
            +
                  @codec.encode(event)
         | 
| 222 | 
            +
                end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                batch = @thread_batch_map[t]
         | 
| 225 | 
            +
                if batch.any?
         | 
| 226 | 
            +
                  retrying_send(batch)
         | 
| 227 | 
            +
                  batch.clear
         | 
| 195 228 | 
             
                end
         | 
| 196 | 
            -
             | 
| 229 | 
            +
              end
         | 
| 230 | 
            +
             | 
| 231 | 
            +
              def retrying_send(batch)
         | 
| 232 | 
            +
                remaining = @retries;
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                while batch.any?
         | 
| 235 | 
            +
                  if !remaining.nil?
         | 
| 236 | 
            +
                    if remaining < 0
         | 
| 237 | 
            +
                      # TODO(sissel): Offer to DLQ? Then again, if it's a transient fault,
         | 
| 238 | 
            +
                      # DLQing would make things worse (you dlq data that would be successful
         | 
| 239 | 
            +
                      # after the fault is repaired)
         | 
| 240 | 
            +
                      logger.info("Exhausted user-configured retry count when sending to Kafka. Dropping these events.",
         | 
| 241 | 
            +
                                  :max_retries => @retries, :drop_count => batch.count)
         | 
| 242 | 
            +
                      break
         | 
| 243 | 
            +
                    end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                    remaining -= 1
         | 
| 246 | 
            +
                  end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                  failures = []
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                  futures = batch.collect do |record| 
         | 
| 251 | 
            +
                    begin
         | 
| 252 | 
            +
                      # send() can throw an exception even before the future is created.
         | 
| 253 | 
            +
                      @producer.send(record)
         | 
| 254 | 
            +
                    rescue org.apache.kafka.common.errors.TimeoutException => e
         | 
| 255 | 
            +
                      failures << record
         | 
| 256 | 
            +
                      nil
         | 
| 257 | 
            +
                    rescue org.apache.kafka.common.errors.InterruptException => e
         | 
| 258 | 
            +
                      failures << record
         | 
| 259 | 
            +
                      nil
         | 
| 260 | 
            +
                    rescue org.apache.kafka.common.errors.SerializationException => e
         | 
| 261 | 
            +
                      # TODO(sissel): Retrying will fail because the data itself has a problem serializing.
         | 
| 262 | 
            +
                      # TODO(sissel): Let's add DLQ here.
         | 
| 263 | 
            +
                      failures << record
         | 
| 264 | 
            +
                      nil
         | 
| 265 | 
            +
                    end
         | 
| 266 | 
            +
                  end.compact
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                  futures.each_with_index do |future, i|
         | 
| 269 | 
            +
                    begin
         | 
| 270 | 
            +
                      result = future.get()
         | 
| 271 | 
            +
                    rescue => e
         | 
| 272 | 
            +
                      # TODO(sissel): Add metric to count failures, possibly by exception type.
         | 
| 273 | 
            +
                      logger.debug? && logger.debug("KafkaProducer.send() failed: #{e}", :exception => e);
         | 
| 274 | 
            +
                      failures << batch[i]
         | 
| 275 | 
            +
                    end
         | 
| 276 | 
            +
                  end
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                  # No failures? Cool. Let's move on.
         | 
| 279 | 
            +
                  break if failures.empty?
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                  # Otherwise, retry with any failed transmissions
         | 
| 282 | 
            +
                  batch = failures
         | 
| 283 | 
            +
                  delay = 1.0 / @retry_backoff_ms
         | 
| 284 | 
            +
                  logger.info("Sending batch to Kafka failed. Will retry after a delay.", :batch_size => batch.size,
         | 
| 285 | 
            +
                              :failures => failures.size, :sleep => delay);
         | 
| 286 | 
            +
                  sleep(delay)
         | 
| 287 | 
            +
                end
         | 
| 288 | 
            +
             | 
| 197 289 | 
             
              end
         | 
| 198 290 |  | 
| 199 291 | 
             
              def close
         | 
| @@ -217,8 +309,8 @@ class LogStash::Outputs::Kafka < LogStash::Outputs::Base | |
| 217 309 | 
             
                  props.put(kafka::MAX_REQUEST_SIZE_CONFIG, max_request_size.to_s)
         | 
| 218 310 | 
             
                  props.put(kafka::RECONNECT_BACKOFF_MS_CONFIG, reconnect_backoff_ms) unless reconnect_backoff_ms.nil?
         | 
| 219 311 | 
             
                  props.put(kafka::REQUEST_TIMEOUT_MS_CONFIG, request_timeout_ms) unless request_timeout_ms.nil?
         | 
| 220 | 
            -
                  props.put(kafka::RETRIES_CONFIG, retries.to_s)
         | 
| 221 | 
            -
                  props.put(kafka::RETRY_BACKOFF_MS_CONFIG, retry_backoff_ms.to_s)
         | 
| 312 | 
            +
                  props.put(kafka::RETRIES_CONFIG, retries.to_s) unless retries.nil?
         | 
| 313 | 
            +
                  props.put(kafka::RETRY_BACKOFF_MS_CONFIG, retry_backoff_ms.to_s) 
         | 
| 222 314 | 
             
                  props.put(kafka::SEND_BUFFER_CONFIG, send_buffer_bytes.to_s)
         | 
| 223 315 | 
             
                  props.put(kafka::VALUE_SERIALIZER_CLASS_CONFIG, value_serializer)
         | 
| 224 316 |  | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 |  | 
| 3 3 | 
             
              s.name            = 'logstash-output-kafka'
         | 
| 4 | 
            -
              s.version         = '7.0. | 
| 4 | 
            +
              s.version         = '7.0.3'
         | 
| 5 5 | 
             
              s.licenses        = ['Apache License (2.0)']
         | 
| 6 6 | 
             
              s.summary         = 'Output events to a Kafka topic. This uses the Kafka Producer API to write messages to a topic on the broker'
         | 
| 7 7 | 
             
              s.description     = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
         | 
| @@ -157,7 +157,7 @@ describe "outputs/kafka", :integration => true do | |
| 157 157 | 
             
              def load_kafka_data(config)
         | 
| 158 158 | 
             
                kafka = LogStash::Outputs::Kafka.new(config)
         | 
| 159 159 | 
             
                kafka.register
         | 
| 160 | 
            -
                num_events.times  | 
| 160 | 
            +
                kafka.multi_receive(num_events.times.collect { event })
         | 
| 161 161 | 
             
                kafka.close
         | 
| 162 162 | 
             
              end
         | 
| 163 163 |  | 
| @@ -25,34 +25,118 @@ describe "outputs/kafka" do | |
| 25 25 | 
             
              context 'when outputting messages' do
         | 
| 26 26 | 
             
                it 'should send logstash event to kafka broker' do
         | 
| 27 27 | 
             
                  expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send)
         | 
| 28 | 
            -
                    .with(an_instance_of(org.apache.kafka.clients.producer.ProducerRecord))
         | 
| 28 | 
            +
                    .with(an_instance_of(org.apache.kafka.clients.producer.ProducerRecord)).and_call_original
         | 
| 29 29 | 
             
                  kafka = LogStash::Outputs::Kafka.new(simple_kafka_config)
         | 
| 30 30 | 
             
                  kafka.register
         | 
| 31 | 
            -
                  kafka. | 
| 31 | 
            +
                  kafka.multi_receive([event])
         | 
| 32 32 | 
             
                end
         | 
| 33 33 |  | 
| 34 34 | 
             
                it 'should support Event#sprintf placeholders in topic_id' do
         | 
| 35 35 | 
             
                  topic_field = 'topic_name'
         | 
| 36 36 | 
             
                  expect(org.apache.kafka.clients.producer.ProducerRecord).to receive(:new)
         | 
| 37 | 
            -
                    .with("my_topic", event.to_s)
         | 
| 38 | 
            -
                  expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send)
         | 
| 37 | 
            +
                    .with("my_topic", event.to_s).and_call_original
         | 
| 38 | 
            +
                  expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send).and_call_original
         | 
| 39 39 | 
             
                  kafka = LogStash::Outputs::Kafka.new({'topic_id' => "%{#{topic_field}}"})
         | 
| 40 40 | 
             
                  kafka.register
         | 
| 41 | 
            -
                  kafka. | 
| 41 | 
            +
                  kafka.multi_receive([event])
         | 
| 42 42 | 
             
                end
         | 
| 43 43 |  | 
| 44 44 | 
             
                it 'should support field referenced message_keys' do
         | 
| 45 45 | 
             
                  expect(org.apache.kafka.clients.producer.ProducerRecord).to receive(:new)
         | 
| 46 | 
            -
                    .with("test", "172.0.0.1", event.to_s)
         | 
| 47 | 
            -
                  expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send)
         | 
| 46 | 
            +
                    .with("test", "172.0.0.1", event.to_s).and_call_original
         | 
| 47 | 
            +
                  expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send).and_call_original
         | 
| 48 48 | 
             
                  kafka = LogStash::Outputs::Kafka.new(simple_kafka_config.merge({"message_key" => "%{host}"}))
         | 
| 49 49 | 
             
                  kafka.register
         | 
| 50 | 
            -
                  kafka. | 
| 50 | 
            +
                  kafka.multi_receive([event])
         | 
| 51 51 | 
             
                end
         | 
| 52 52 |  | 
| 53 53 | 
             
                it 'should raise config error when truststore location is not set and ssl is enabled' do
         | 
| 54 | 
            -
                  kafka = LogStash::Outputs::Kafka.new(simple_kafka_config.merge( | 
| 54 | 
            +
                  kafka = LogStash::Outputs::Kafka.new(simple_kafka_config.merge("security_protocol" => "SSL"))
         | 
| 55 55 | 
             
                  expect { kafka.register }.to raise_error(LogStash::ConfigurationError, /ssl_truststore_location must be set when SSL is enabled/)
         | 
| 56 56 | 
             
                end
         | 
| 57 57 | 
             
              end
         | 
| 58 | 
            +
              
         | 
| 59 | 
            +
              context "when KafkaProducer#send() raises an exception" do
         | 
| 60 | 
            +
                let(:failcount) { (rand * 10).to_i }
         | 
| 61 | 
            +
                let(:sendcount) { failcount + 1 }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                let(:exception_classes) { [
         | 
| 64 | 
            +
                  org.apache.kafka.common.errors.TimeoutException,
         | 
| 65 | 
            +
                  org.apache.kafka.common.errors.InterruptException,
         | 
| 66 | 
            +
                  org.apache.kafka.common.errors.SerializationException
         | 
| 67 | 
            +
                ] }
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                before do
         | 
| 70 | 
            +
                  count = 0
         | 
| 71 | 
            +
                  expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send)
         | 
| 72 | 
            +
                    .exactly(sendcount).times
         | 
| 73 | 
            +
                    .and_wrap_original do |m, *args|
         | 
| 74 | 
            +
                    if count < failcount # fail 'failcount' times in a row.
         | 
| 75 | 
            +
                      count += 1
         | 
| 76 | 
            +
                      # Pick an exception at random
         | 
| 77 | 
            +
                      raise exception_classes.shuffle.first.new("injected exception for testing")
         | 
| 78 | 
            +
                    else
         | 
| 79 | 
            +
                      m.call(*args) # call original
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                it "should retry until successful" do
         | 
| 85 | 
            +
                  kafka = LogStash::Outputs::Kafka.new(simple_kafka_config)
         | 
| 86 | 
            +
                  kafka.register
         | 
| 87 | 
            +
                  kafka.multi_receive([event])
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              context "when a send fails" do
         | 
| 92 | 
            +
                context "and the default retries behavior is used" do
         | 
| 93 | 
            +
                  # Fail this many times and then finally succeed.
         | 
| 94 | 
            +
                  let(:failcount) { (rand * 10).to_i }
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  # Expect KafkaProducer.send() to get called again after every failure, plus the successful one.
         | 
| 97 | 
            +
                  let(:sendcount) { failcount + 1 }
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  it "should retry until successful" do
         | 
| 100 | 
            +
                    count = 0;
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send)
         | 
| 103 | 
            +
                          .exactly(sendcount).times
         | 
| 104 | 
            +
                          .and_wrap_original do |m, *args|
         | 
| 105 | 
            +
                      if count < failcount
         | 
| 106 | 
            +
                        count += 1
         | 
| 107 | 
            +
                        # inject some failures.
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                        # Return a custom Future that will raise an exception to simulate a Kafka send() problem.
         | 
| 110 | 
            +
                        future = java.util.concurrent.FutureTask.new { raise "Failed" }
         | 
| 111 | 
            +
                        future.run
         | 
| 112 | 
            +
                        future
         | 
| 113 | 
            +
                      else
         | 
| 114 | 
            +
                        m.call(*args)
         | 
| 115 | 
            +
                      end
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
                    kafka = LogStash::Outputs::Kafka.new(simple_kafka_config)
         | 
| 118 | 
            +
                    kafka.register
         | 
| 119 | 
            +
                    kafka.multi_receive([event])
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                context "and when retries is set by the user" do
         | 
| 124 | 
            +
                  let(:retries) { (rand * 10).to_i }
         | 
| 125 | 
            +
                  let(:max_sends) { retries + 1 }
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                  it "should give up after retries are exhausted" do
         | 
| 128 | 
            +
                    expect_any_instance_of(org.apache.kafka.clients.producer.KafkaProducer).to receive(:send)
         | 
| 129 | 
            +
                          .at_most(max_sends).times
         | 
| 130 | 
            +
                          .and_wrap_original do |m, *args|
         | 
| 131 | 
            +
                      # Always fail.
         | 
| 132 | 
            +
                      future = java.util.concurrent.FutureTask.new { raise "Failed" }
         | 
| 133 | 
            +
                      future.run
         | 
| 134 | 
            +
                      future
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
                    kafka = LogStash::Outputs::Kafka.new(simple_kafka_config.merge("retries" => retries))
         | 
| 137 | 
            +
                    kafka.register
         | 
| 138 | 
            +
                    kafka.multi_receive([event])
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
              end
         | 
| 58 142 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: logstash-output-kafka
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 7.0. | 
| 4 | 
            +
              version: 7.0.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Elasticsearch
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2017- | 
| 11 | 
            +
            date: 2017-10-09 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              requirement: !ruby/object:Gem::Requirement
         |