logstash-input-kinesis-jordanforks 2.0.9-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.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +29 -0
  3. data/CONTRIBUTORS +14 -0
  4. data/Gemfile +11 -0
  5. data/README.md +82 -0
  6. data/lib/logstash/inputs/kinesis.rb +135 -0
  7. data/lib/logstash/inputs/kinesis/version.rb +8 -0
  8. data/lib/logstash/inputs/kinesis/worker.rb +67 -0
  9. data/logstash-input-kinesis.gemspec +33 -0
  10. data/spec/inputs/kinesis/worker_spec.rb +110 -0
  11. data/spec/inputs/kinesis_spec.rb +155 -0
  12. data/spec/spec_helper.rb +17 -0
  13. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/amazon-kinesis-client/1.9.2/amazon-kinesis-client-1.9.2.jar +0 -0
  14. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-cloudwatch/1.11.400/aws-java-sdk-cloudwatch-1.11.400.jar +0 -0
  15. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-core/1.11.414/aws-java-sdk-core-1.11.414.jar +0 -0
  16. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-dynamodb/1.11.400/aws-java-sdk-dynamodb-1.11.400.jar +0 -0
  17. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-kinesis/1.11.400/aws-java-sdk-kinesis-1.11.400.jar +0 -0
  18. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-kms/1.11.400/aws-java-sdk-kms-1.11.400.jar +0 -0
  19. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-s3/1.11.400/aws-java-sdk-s3-1.11.400.jar +0 -0
  20. data/vendor/jar-dependencies/runtime-jars/com/amazonaws/jmespath-java/1.11.400/jmespath-java-1.11.400.jar +0 -0
  21. data/vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/core/jackson-annotations/2.6.0/jackson-annotations-2.6.0.jar +0 -0
  22. data/vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/core/jackson-core/2.6.7/jackson-core-2.6.7.jar +0 -0
  23. data/vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/core/jackson-databind/2.6.7.1/jackson-databind-2.6.7.1.jar +0 -0
  24. data/vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/dataformat/jackson-dataformat-cbor/2.6.7/jackson-dataformat-cbor-2.6.7.jar +0 -0
  25. data/vendor/jar-dependencies/runtime-jars/com/google/guava/guava/18.0/guava-18.0.jar +0 -0
  26. data/vendor/jar-dependencies/runtime-jars/com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.jar +0 -0
  27. data/vendor/jar-dependencies/runtime-jars/commons-codec/commons-codec/1.10/commons-codec-1.10.jar +0 -0
  28. data/vendor/jar-dependencies/runtime-jars/commons-lang/commons-lang/2.6/commons-lang-2.6.jar +0 -0
  29. data/vendor/jar-dependencies/runtime-jars/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar +0 -0
  30. data/vendor/jar-dependencies/runtime-jars/joda-time/joda-time/2.8.1/joda-time-2.8.1.jar +0 -0
  31. data/vendor/jar-dependencies/runtime-jars/logstash-input-kinesis-jordanforks_jars.rb +50 -0
  32. data/vendor/jar-dependencies/runtime-jars/org/apache/httpcomponents/httpclient/4.5.5/httpclient-4.5.5.jar +0 -0
  33. data/vendor/jar-dependencies/runtime-jars/org/apache/httpcomponents/httpcore/4.4.9/httpcore-4.4.9.jar +0 -0
  34. data/vendor/jar-dependencies/runtime-jars/software/amazon/ion/ion-java/1.0.2/ion-java-1.0.2.jar +0 -0
  35. metadata +149 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a4dc414ade512afb167ae00c53e1b249d36eef6c
4
+ data.tar.gz: 5e6ec3fe52595870639712fd799fc79b319e4958
5
+ SHA512:
6
+ metadata.gz: f788fc5cdcc8ecd190d21adc7f4bf56688dab1328ed7eb57853aa07fe67e4735ee708b70c5d1167161170ecd73768b6e906a05c0a3fffaaaa4fd9acce03c7926
7
+ data.tar.gz: f27efa5cc4d15fae4e9f503b41746e38f8e1d2e564878d32d48d8fa20dd3d910a10372f75d6bee9af92d78653145ffa4d7d209713ed0641a953c987ce29ab3a5
data/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ ## 2.0.8
2
+ - Changed plugin to use more recent versions of Kinesis Client library and AWS SDK[#45](https://github.com/logstash-plugins/logstash-input-kinesis/pull/45)
3
+
4
+ ## 2.0.7
5
+ - Docs: Set the default_codec doc attribute.
6
+
7
+ ## 2.0.7
8
+ - Update gemspec summary
9
+
10
+ ## 2.0.6
11
+ - Fix some documentation issues
12
+ - Add support for `initial_position_in_stream` config parameter. `TRIM_HORIZON` and `LATEST` are supported.
13
+
14
+ ## 2.0.5
15
+ - Docs: Add CHANGELOG.md
16
+ - Support for specifying an AWS credentials profile with the `profile` config parameter
17
+ - Docs: Remove extraneous text added during doc extract
18
+
19
+ ## 2.0.4
20
+ - Docs: Bump version for automated doc build
21
+
22
+ ## 2.0.3
23
+ - Fix error about failed to coerce java.util.logging.Level to org.apache.log4j.Level with logstash 5.1.1
24
+
25
+ ## 2.0.2
26
+ - Fix error with Logstash 5.0
27
+
28
+ ## 2.0.1
29
+ - Add partition_key, approximate_arrival_timestamp and sequence_number fields in the @metadata sub-has
data/CONTRIBUTORS ADDED
@@ -0,0 +1,14 @@
1
+ The following is a list of people who have contributed ideas, code, bug
2
+ reports, or in general have helped logstash along its way.
3
+
4
+ Maintainers:
5
+ * Brian Palmer (codekitchen)
6
+
7
+ Contributors:
8
+ * Brian Palmer (codekitchen)
9
+ * Samuel García Martínez (samuelgmartinez)
10
+
11
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
12
+ Logstash, and you aren't on the list above and want to be, please let us know
13
+ and we'll make sure you're here. Contributions from folks like you are what make
14
+ open source awesome.
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ logstash_path = ENV["LOGSTASH_PATH"] || "../../logstash"
6
+ use_logstash_source = ENV["LOGSTASH_SOURCE"] && ENV["LOGSTASH_SOURCE"].to_s == "1"
7
+
8
+ if Dir.exist?(logstash_path) && use_logstash_source
9
+ gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
10
+ gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
11
+ end
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Logstash AWS Kinesis Input Plugin
2
+
3
+ [![Build Status](https://travis-ci.org/logstash-plugins/logstash-input-kinesis.svg)](https://travis-ci.org/logstash-plugins/logstash-input-kinesis)
4
+
5
+ This is a [AWS Kinesis](http://docs.aws.amazon.com/kinesis/latest/dev/introduction.html) input plugin for [Logstash](https://github.com/elasticsearch/logstash). Under the hood uses the [Kinesis Client Library](http://docs.aws.amazon.com/kinesis/latest/dev/kinesis-record-processor-implementation-app-java.html).
6
+
7
+ ## Installation
8
+
9
+ This plugin requires Logstash >= 2.0, and can be installed by Logstash
10
+ itself.
11
+
12
+ ```sh
13
+ bin/logstash-plugin install logstash-input-kinesis
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```
19
+ input {
20
+ kinesis {
21
+ kinesis_stream_name => "my-logging-stream"
22
+ codec => json { }
23
+ }
24
+ }
25
+ ```
26
+
27
+ ### Using with CloudWatch Logs
28
+
29
+ If you are looking to read a CloudWatch Logs subscription stream, you'll also want to install and configure the [CloudWatch Logs Codec](https://github.com/threadwaste/logstash-codec-cloudwatch_logs).
30
+
31
+ ## Configuration
32
+
33
+ This are the properties you can configure and what are the default values:
34
+
35
+ * `application_name`: The name of the application used in DynamoDB for coordination. Only one worker per unique stream partition and application will be actively consuming messages.
36
+ * **required**: false
37
+ * **default value**: `logstash`
38
+ * `kinesis_stream_name`: The Kinesis stream name.
39
+ * **required**: true
40
+ * `region`: The AWS region name for Kinesis, DynamoDB and Cloudwatch (if enabled)
41
+ * **required**: false
42
+ * **default value**: `us-east-1`
43
+ * `checkpoint_interval_seconds`: How many seconds between worker checkpoints to DynamoDB. A low value ussually means lower message replay in case of node failure/restart but it increases CPU+network ussage (which increases the AWS costs).
44
+ * **required**: false
45
+ * **default value**: `60`
46
+ * `failover_time_millis`: How many milliseconds to wait since the last checkpoint before a new worker should take over the lease.
47
+ * **required**: false
48
+ * **default value**: `120000`
49
+ * `metrics`: Worker metric tracking. By default this is disabled, set it to "cloudwatch" to enable the cloudwatch integration in the Kinesis Client Library.
50
+ * **required**: false
51
+ * **default value**: `nil`
52
+ * `profile`: The AWS profile name for authentication. This ensures that the `~/.aws/credentials` AWS auth provider is used. By default this is empty and the default chain will be used.
53
+ * **required**: false
54
+ * **default value**: `""`
55
+ * `initial_position_in_stream`: The value for initialPositionInStream. Accepts "TRIM_HORIZON" or "LATEST".
56
+ * **required**: false
57
+ * **default value**: `"TRIM_HORIZON"`
58
+
59
+ ## Authentication
60
+
61
+ This plugin uses the default AWS SDK auth chain, [DefaultAWSCredentialsProviderChain](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html), to determine which credentials the client will use, unless `profile` is set, in which case [ProfileCredentialsProvider](http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/profile/ProfileCredentialsProvider.html) is used.
62
+
63
+ The default chain follows this order trying to read the credentials:
64
+ * `AWS_ACCESS_KEY_ID` / `AWS_SECRET_KEY` environment variables
65
+ * `~/.aws/credentials` credentials file
66
+ * EC2 instance profile
67
+
68
+ The credentials will need access to the following services:
69
+ * AWS Kinesis
70
+ * AWS DynamoDB: the client library stores information for worker coordination in DynamoDB (offsets and active worker per partition)
71
+ * AWS CloudWatch: if the metrics are enabled the credentials need CloudWatch update permisions granted.
72
+
73
+ Look at the [documentation](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html) for deeper information on the default chain.
74
+
75
+ ## Contributing
76
+
77
+ 0. https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md#contribution-steps
78
+ 1. Fork it ( https://github.com/logstash-plugins/logstash-input-kinesis/fork )
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create a new Pull Request
@@ -0,0 +1,135 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/base"
3
+ require "logstash/errors"
4
+ require "logstash/environment"
5
+ require "logstash/namespace"
6
+
7
+ require 'logstash-input-kinesis_jars'
8
+ require "logstash/inputs/kinesis/version"
9
+
10
+
11
+ # Receive events through an AWS Kinesis stream.
12
+ #
13
+ # This input plugin uses the Java Kinesis Client Library underneath, so the
14
+ # documentation at https://github.com/awslabs/amazon-kinesis-client will be
15
+ # useful.
16
+ #
17
+ # AWS credentials can be specified either through environment variables, or an
18
+ # IAM instance role. The library uses a DynamoDB table for worker coordination,
19
+ # so you'll need to grant access to that as well as to the Kinesis stream. The
20
+ # DynamoDB table has the same name as the `application_name` configuration
21
+ # option, which defaults to "logstash".
22
+ #
23
+ # The library can optionally also send worker statistics to CloudWatch.
24
+ class LogStash::Inputs::Kinesis < LogStash::Inputs::Base
25
+ KCL = com.amazonaws.services.kinesis.clientlibrary.lib.worker
26
+ KCL_PROCESSOR_FACTORY_CLASS = com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessorFactory
27
+ require "logstash/inputs/kinesis/worker"
28
+
29
+ config_name 'kinesis'
30
+
31
+ attr_reader(
32
+ :kcl_config,
33
+ :kcl_worker,
34
+ )
35
+
36
+ # The application name used for the dynamodb coordination table. Must be
37
+ # unique for this kinesis stream.
38
+ config :application_name, :validate => :string, :default => "logstash"
39
+
40
+ # The kinesis stream name.
41
+ config :kinesis_stream_name, :validate => :string, :required => true
42
+
43
+ # The AWS region for Kinesis, DynamoDB, and CloudWatch (if enabled)
44
+ config :region, :validate => :string, :default => "us-east-1"
45
+
46
+ # How many seconds between worker checkpoints to dynamodb.
47
+ config :checkpoint_interval_seconds, :validate => :number, :default => 60
48
+
49
+ # How many milliseconds to wait since the last checkpoint before a new
50
+ # worker should take over the lease.
51
+ config :failover_time_millis, :validate => :number, :default => 120000
52
+
53
+ # Worker metric tracking. By default this is disabled, set it to "cloudwatch"
54
+ # to enable the cloudwatch integration in the Kinesis Client Library.
55
+ config :metrics, :validate => [nil, "cloudwatch"], :default => nil
56
+
57
+ # Select AWS profile for input
58
+ config :profile, :validate => :string
59
+
60
+ # Select initial_position_in_stream. Accepts TRIM_HORIZON or LATEST
61
+ config :initial_position_in_stream, :validate => ["TRIM_HORIZON", "LATEST"], :default => "TRIM_HORIZON"
62
+
63
+ def initialize(params = {})
64
+ super(params)
65
+ end
66
+
67
+ def register
68
+ # the INFO log level is extremely noisy in KCL
69
+ kinesis_logger = org.apache.commons.logging::LogFactory.getLog("com.amazonaws.services.kinesis").logger
70
+ if kinesis_logger.java_kind_of?(java.util.logging::Logger)
71
+ kinesis_logger.setLevel(java.util.logging::Level::WARNING)
72
+ else
73
+ kinesis_logger.setLevel(org.apache.log4j::Level::WARN)
74
+ end
75
+
76
+ worker_id = java.util::UUID.randomUUID.to_s
77
+
78
+ # If the AWS profile is set, use the profile credentials provider.
79
+ # Otherwise fall back to the default chain.
80
+ unless @profile.nil?
81
+ creds = com.amazonaws.auth.profile::ProfileCredentialsProvider.new(@profile)
82
+ else
83
+ creds = com.amazonaws.auth::DefaultAWSCredentialsProviderChain.new
84
+ end
85
+ initial_position_in_stream = if @initial_position_in_stream == "TRIM_HORIZON"
86
+ KCL::InitialPositionInStream::TRIM_HORIZON
87
+ else
88
+ KCL::InitialPositionInStream::LATEST
89
+ end
90
+
91
+ @kcl_config = KCL::KinesisClientLibConfiguration.new(
92
+ @application_name,
93
+ @kinesis_stream_name,
94
+ creds,
95
+ worker_id).
96
+ withInitialPositionInStream(initial_position_in_stream).
97
+ withRegionName(@region).
98
+ withFailoverTimeMillis(@failover_time_millis)
99
+ end
100
+
101
+ def run(output_queue)
102
+ @kcl_worker = kcl_builder(output_queue).build
103
+ @kcl_worker.run
104
+ end
105
+
106
+ def kcl_builder(output_queue)
107
+ KCL::Worker::Builder.new.tap do |builder|
108
+ builder.java_send(:recordProcessorFactory, [KCL_PROCESSOR_FACTORY_CLASS.java_class], worker_factory(output_queue))
109
+ builder.config(@kcl_config)
110
+
111
+ if metrics_factory
112
+ builder.metricsFactory(metrics_factory)
113
+ end
114
+ end
115
+ end
116
+
117
+ def stop
118
+ @kcl_worker.shutdown if @kcl_worker
119
+ end
120
+
121
+ def worker_factory(output_queue)
122
+ proc { Worker.new(@codec.clone, output_queue, method(:decorate), @checkpoint_interval_seconds, @logger) }
123
+ end
124
+
125
+ protected
126
+
127
+ def metrics_factory
128
+ case @metrics
129
+ when nil
130
+ com.amazonaws.services.kinesis.metrics.impl::NullMetricsFactory.new
131
+ when 'cloudwatch'
132
+ nil # default in the underlying library
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ module Logstash
3
+ module Input
4
+ module Kinesis
5
+ VERSION = "2.0.9"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+ class LogStash::Inputs::Kinesis::Worker
3
+ include com.amazonaws.services.kinesis.clientlibrary.interfaces.v2::IRecordProcessor
4
+
5
+ attr_reader(
6
+ :checkpoint_interval,
7
+ :codec,
8
+ :decorator,
9
+ :logger,
10
+ :output_queue,
11
+ )
12
+
13
+ def initialize(*args)
14
+ # nasty hack, because this is the name of a method on IRecordProcessor, but also ruby's constructor
15
+ if !@constructed
16
+ @codec, @output_queue, @decorator, @checkpoint_interval, @logger = args
17
+ @next_checkpoint = Time.now - 600
18
+ @constructed = true
19
+ else
20
+ _shard_id = args[0].shardId
21
+ end
22
+ end
23
+ public :initialize
24
+
25
+ def processRecords(records_input)
26
+ records_input.records.each { |record| process_record(record) }
27
+ if Time.now >= @next_checkpoint
28
+ checkpoint(records_input.checkpointer)
29
+ @next_checkpoint = Time.now + @checkpoint_interval
30
+ end
31
+ end
32
+
33
+ def shutdown(shutdown_input)
34
+ if shutdown_input.shutdown_reason == com.amazonaws.services.kinesis.clientlibrary.lib.worker::ShutdownReason::TERMINATE
35
+ checkpoint(shutdown_input.checkpointer)
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ def checkpoint(checkpointer)
42
+ checkpointer.checkpoint()
43
+ rescue => error
44
+ @logger.error("Kinesis worker failed checkpointing: #{error}")
45
+ end
46
+
47
+ def process_record(record)
48
+ raw = String.from_java_bytes(record.getData.array)
49
+ metadata = build_metadata(record)
50
+ @codec.decode(raw) do |event|
51
+ @decorator.call(event)
52
+ event.set('@metadata', metadata)
53
+ @output_queue << event
54
+ end
55
+ rescue => error
56
+ @logger.error("Error processing record: #{error}")
57
+ end
58
+
59
+ def build_metadata(record)
60
+ metadata = Hash.new
61
+ metadata['approximate_arrival_timestamp'] = record.getApproximateArrivalTimestamp.getTime
62
+ metadata['partition_key'] = record.getPartitionKey
63
+ metadata['sequence_number'] = record.getSequenceNumber
64
+ metadata
65
+ end
66
+
67
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'logstash/inputs/kinesis/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "logstash-input-kinesis-jordanforks"
8
+ spec.version = Logstash::Input::Kinesis::VERSION
9
+ spec.authors = ["Brian Palmer"]
10
+ spec.email = ["brian@codekitchen.net"]
11
+ spec.summary = "Receives events through an AWS Kinesis stream"
12
+ spec.description = %q{This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program}
13
+ spec.homepage = "https://github.com/logstash-plugins/logstash-input-kinesis"
14
+ spec.licenses = ['Apache-2.0']
15
+
16
+ spec.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib', 'vendor/jar-dependencies/runtime-jars']
19
+
20
+ # Special flag to let us know this is actually a logstash plugin
21
+ spec.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
22
+
23
+ spec.platform = 'java'
24
+
25
+ spec.requirements << "jar 'com.amazonaws:amazon-kinesis-client', '1.9.2'"
26
+ spec.requirements << "jar 'com.amazonaws:aws-java-sdk-core', '1.11.414'"
27
+
28
+ spec.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
29
+
30
+ spec.add_development_dependency 'logstash-devutils'
31
+ spec.add_development_dependency 'jar-dependencies', '~> 0.3.4'
32
+ spec.add_development_dependency "logstash-codec-json"
33
+ end
@@ -0,0 +1,110 @@
1
+ require 'logstash-core/logstash-core'
2
+ require 'logstash-input-kinesis_jars'
3
+ require "logstash/plugin"
4
+ require "logstash/inputs/kinesis"
5
+ require "logstash/codecs/json"
6
+ require "json"
7
+
8
+ RSpec.describe "LogStash::Inputs::Kinesis::Worker" do
9
+ KCL_TYPES = com.amazonaws.services.kinesis.clientlibrary.types
10
+
11
+ subject!(:worker) { LogStash::Inputs::Kinesis::Worker.new(codec, queue, decorator, checkpoint_interval) }
12
+ let(:codec) { LogStash::Codecs::JSON.new() }
13
+ let(:queue) { Queue.new }
14
+ let(:decorator) { proc { |x| x.set('decorated', true); x } }
15
+ let(:checkpoint_interval) { 120 }
16
+ let(:checkpointer) { double('checkpointer', checkpoint: nil) }
17
+ let(:init_input) { KCL_TYPES::InitializationInput.new().withShardId("xyz") }
18
+
19
+ it "honors the initialize java interface method contract" do
20
+ expect { worker.initialize(init_input) }.to_not raise_error
21
+ end
22
+
23
+ def record(hash = { "message" => "test" }, arrival_timestamp, partition_key, sequence_number)
24
+ encoder = java.nio.charset::Charset.forName("UTF-8").newEncoder()
25
+ data = encoder.encode(java.nio.CharBuffer.wrap(JSON.generate(hash)))
26
+ double(
27
+ getData: data,
28
+ getApproximateArrivalTimestamp: java.util.Date.new(arrival_timestamp.to_f * 1000),
29
+ getPartitionKey: partition_key,
30
+ getSequenceNumber: sequence_number
31
+ )
32
+ end
33
+
34
+ let(:process_input) {
35
+ KCL_TYPES::ProcessRecordsInput.new()
36
+ .withRecords(java.util.Arrays.asList([
37
+ record(
38
+ {
39
+ id: "record1",
40
+ message: "test1"
41
+ },
42
+ '1.441215410867E9',
43
+ 'partitionKey1',
44
+ '21269319989652663814458848515492872191'
45
+ ),
46
+ record(
47
+ {
48
+ id: "record2",
49
+ message: "test2"
50
+ },
51
+ '1.441215410868E9',
52
+ 'partitionKey2',
53
+ '21269319989652663814458848515492872192'
54
+ )].to_java)
55
+ )
56
+ .withCheckpointer(checkpointer)
57
+ }
58
+ let(:empty_process_input) {
59
+ KCL_TYPES::ProcessRecordsInput.new()
60
+ .withRecords(java.util.Arrays.asList([].to_java))
61
+ .withCheckpointer(checkpointer)
62
+ }
63
+
64
+ context "initialized" do
65
+ before do
66
+ worker.initialize(init_input)
67
+ end
68
+
69
+ describe "#processRecords" do
70
+ it "decodes and queues each record with decoration" do
71
+ worker.processRecords(process_input)
72
+ expect(queue.size).to eq(2)
73
+ m1 = queue.pop
74
+ m2 = queue.pop
75
+ expect(m1).to be_kind_of(LogStash::Event)
76
+ expect(m2).to be_kind_of(LogStash::Event)
77
+ expect(m1.get('id')).to eq("record1")
78
+ expect(m1.get('message')).to eq("test1")
79
+ expect(m1.get('@metadata')['approximate_arrival_timestamp']).to eq(1441215410867)
80
+ expect(m1.get('@metadata')['partition_key']).to eq('partitionKey1')
81
+ expect(m1.get('@metadata')['sequence_number']).to eq('21269319989652663814458848515492872191')
82
+ expect(m1.get('decorated')).to eq(true)
83
+ end
84
+
85
+ it "checkpoints on interval" do
86
+ expect(checkpointer).to receive(:checkpoint).once
87
+ worker.processRecords(empty_process_input)
88
+
89
+ # not this time
90
+ worker.processRecords(empty_process_input)
91
+
92
+ allow(Time).to receive(:now).and_return(Time.now + 125)
93
+ expect(checkpointer).to receive(:checkpoint).once
94
+ worker.processRecords(empty_process_input)
95
+ end
96
+ end
97
+
98
+ describe "#shutdown" do
99
+ it "checkpoints on termination" do
100
+ input = KCL_TYPES::ShutdownInput.new
101
+ checkpointer = double('checkpointer')
102
+ expect(checkpointer).to receive(:checkpoint)
103
+ input.
104
+ with_shutdown_reason(com.amazonaws.services.kinesis.clientlibrary.lib.worker::ShutdownReason::TERMINATE).
105
+ with_checkpointer(checkpointer)
106
+ worker.shutdown(input)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,155 @@
1
+ require "logstash/plugin"
2
+ require "logstash/inputs/kinesis"
3
+ require "logstash/codecs/json"
4
+
5
+ RSpec.describe "inputs/kinesis" do
6
+ KCL = com.amazonaws.services.kinesis.clientlibrary.lib.worker
7
+
8
+ let(:config) {{
9
+ "application_name" => "my-processor",
10
+ "kinesis_stream_name" => "run-specs",
11
+ "codec" => codec,
12
+ "metrics" => metrics,
13
+ "checkpoint_interval_seconds" => 120,
14
+ "failover_time_millis" => 30000,
15
+ "region" => "ap-southeast-1",
16
+ "profile" => nil
17
+ }}
18
+
19
+ # Config hash to test credentials provider to be used if profile is specified
20
+ let(:config_with_profile) {{
21
+ "application_name" => "my-processor",
22
+ "kinesis_stream_name" => "run-specs",
23
+ "codec" => codec,
24
+ "metrics" => metrics,
25
+ "checkpoint_interval_seconds" => 120,
26
+ "failover_time_millis" => 30000,
27
+ "region" => "ap-southeast-1",
28
+ "profile" => "my-aws-profile"
29
+ }}
30
+
31
+ # other config with LATEST as initial_position_in_stream
32
+ let(:config_with_latest) {{
33
+ "application_name" => "my-processor",
34
+ "kinesis_stream_name" => "run-specs",
35
+ "codec" => codec,
36
+ "metrics" => metrics,
37
+ "checkpoint_interval_seconds" => 120,
38
+ "failover_time_millis" => 30000,
39
+ "region" => "ap-southeast-1",
40
+ "profile" => nil,
41
+ "initial_position_in_stream" => "LATEST"
42
+ }}
43
+
44
+ subject!(:kinesis) { LogStash::Inputs::Kinesis.new(config) }
45
+ let(:kcl_worker) { double('kcl_worker') }
46
+ let(:stub_builder) { double('kcl_builder', build: kcl_worker) }
47
+ let(:metrics) { nil }
48
+ let(:codec) { LogStash::Codecs::JSON.new() }
49
+ let(:queue) { Queue.new }
50
+
51
+ it "registers without error" do
52
+ input = LogStash::Plugin.lookup("input", "kinesis").new("kinesis_stream_name" => "specs", "codec" => codec)
53
+ expect { input.register }.to_not raise_error
54
+ end
55
+
56
+ it "configures the KCL" do
57
+ kinesis.register
58
+ expect(kinesis.kcl_config.applicationName).to eq("my-processor")
59
+ expect(kinesis.kcl_config.streamName).to eq("run-specs")
60
+ expect(kinesis.kcl_config.regionName).to eq("ap-southeast-1")
61
+ expect(kinesis.kcl_config.initialPositionInStream).to eq(KCL::InitialPositionInStream::TRIM_HORIZON)
62
+ expect(kinesis.kcl_config.get_kinesis_credentials_provider.getClass.to_s).to eq("com.amazonaws.auth.DefaultAWSCredentialsProviderChain")
63
+ end
64
+
65
+ subject!(:kinesis_with_profile) { LogStash::Inputs::Kinesis.new(config_with_profile) }
66
+
67
+ it "uses ProfileCredentialsProvider if profile is specified" do
68
+ kinesis_with_profile.register
69
+ expect(kinesis_with_profile.kcl_config.get_kinesis_credentials_provider.getClass.to_s).to eq("com.amazonaws.auth.profile.ProfileCredentialsProvider")
70
+ end
71
+
72
+ subject!(:kinesis_with_latest) { LogStash::Inputs::Kinesis.new(config_with_latest) }
73
+
74
+ it "configures the KCL" do
75
+ kinesis_with_latest.register
76
+ expect(kinesis_with_latest.kcl_config.applicationName).to eq("my-processor")
77
+ expect(kinesis_with_latest.kcl_config.streamName).to eq("run-specs")
78
+ expect(kinesis_with_latest.kcl_config.regionName).to eq("ap-southeast-1")
79
+ expect(kinesis_with_latest.kcl_config.initialPositionInStream).to eq(KCL::InitialPositionInStream::LATEST)
80
+ expect(kinesis_with_latest.kcl_config.get_kinesis_credentials_provider.getClass.to_s).to eq("com.amazonaws.auth.DefaultAWSCredentialsProviderChain")
81
+ end
82
+
83
+ context "#run" do
84
+ it "runs the KCL worker" do
85
+ expect(kinesis).to receive(:kcl_builder).with(queue).and_return(stub_builder)
86
+ expect(kcl_worker).to receive(:run).with(no_args)
87
+ builder = kinesis.run(queue)
88
+ end
89
+ end
90
+
91
+ context "#stop" do
92
+ it "stops the KCL worker" do
93
+ expect(kinesis).to receive(:kcl_builder).with(queue).and_return(stub_builder)
94
+ expect(kcl_worker).to receive(:run).with(no_args)
95
+ expect(kcl_worker).to receive(:shutdown).with(no_args)
96
+ kinesis.run(queue)
97
+ kinesis.do_stop # do_stop calls stop internally
98
+ end
99
+ end
100
+
101
+ context "#worker_factory" do
102
+ it "clones the codec for each worker" do
103
+ worker = kinesis.worker_factory(queue).call()
104
+ expect(worker).to be_kind_of(LogStash::Inputs::Kinesis::Worker)
105
+ expect(worker.codec).to_not eq(kinesis.codec)
106
+ expect(worker.codec).to be_kind_of(codec.class)
107
+ end
108
+
109
+ it "generates a valid worker" do
110
+ worker = kinesis.worker_factory(queue).call()
111
+
112
+ expect(worker.codec).to be_kind_of(codec.class)
113
+ expect(worker.checkpoint_interval).to eq(120)
114
+ expect(worker.failover_time_millis).to eq(30000)
115
+ expect(worker.output_queue).to eq(queue)
116
+ expect(worker.decorator).to eq(kinesis.method(:decorate))
117
+ expect(worker.logger).to eq(kinesis.logger)
118
+ end
119
+ end
120
+
121
+ # these tests are heavily dependent on the current Worker::Builder
122
+ # implementation because its state is all private
123
+ context "#kcl_builder" do
124
+ let(:builder) { kinesis.kcl_builder(queue) }
125
+
126
+ it "sets the worker factory" do
127
+ expect(field(builder, "recordProcessorFactory")).to_not eq(nil)
128
+ end
129
+
130
+ it "sets the config" do
131
+ kinesis.register
132
+ config = field(builder, "config")
133
+ expect(config).to eq(kinesis.kcl_config)
134
+ end
135
+
136
+ it "disables metric tracking by default" do
137
+ expect(field(builder, "metricsFactory")).to be_kind_of(com.amazonaws.services.kinesis.metrics.impl::NullMetricsFactory)
138
+ end
139
+
140
+ context "cloudwatch" do
141
+ let(:metrics) { "cloudwatch" }
142
+ it "uses cloudwatch metrics if specified" do
143
+ # since the behaviour is enclosed on private methods it is not testable. So here
144
+ # the expected value can be tested, not the result associated to set this value
145
+ expect(field(builder, "metricsFactory")).to eq(nil)
146
+ end
147
+ end
148
+ end
149
+
150
+ def field(obj, name)
151
+ field = obj.java_class.declared_field(name)
152
+ field.accessible = true
153
+ field.value(obj)
154
+ end
155
+ end
@@ -0,0 +1,17 @@
1
+ RSpec.configure do |config|
2
+ config.expect_with :rspec do |expectations|
3
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
4
+ end
5
+
6
+ config.mock_with :rspec do |mocks|
7
+ mocks.verify_partial_doubles = true
8
+ end
9
+
10
+ config.disable_monkey_patching!
11
+ config.warnings = false
12
+ if config.files_to_run.one?
13
+ config.default_formatter = 'doc'
14
+ end
15
+ config.order = :random
16
+ Kernel.srand config.seed
17
+ end
@@ -0,0 +1,50 @@
1
+ # this is a generated file, to avoid over-writing it just delete this comment
2
+ begin
3
+ require 'jar_dependencies'
4
+ rescue LoadError
5
+ require 'com/fasterxml/jackson/core/jackson-databind/2.6.7.1/jackson-databind-2.6.7.1.jar'
6
+ require 'com/fasterxml/jackson/core/jackson-core/2.6.7/jackson-core-2.6.7.jar'
7
+ require 'com/fasterxml/jackson/dataformat/jackson-dataformat-cbor/2.6.7/jackson-dataformat-cbor-2.6.7.jar'
8
+ require 'org/apache/httpcomponents/httpclient/4.5.5/httpclient-4.5.5.jar'
9
+ require 'com/amazonaws/jmespath-java/1.11.400/jmespath-java-1.11.400.jar'
10
+ require 'com/amazonaws/aws-java-sdk-s3/1.11.400/aws-java-sdk-s3-1.11.400.jar'
11
+ require 'com/google/guava/guava/18.0/guava-18.0.jar'
12
+ require 'commons-lang/commons-lang/2.6/commons-lang-2.6.jar'
13
+ require 'commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar'
14
+ require 'joda-time/joda-time/2.8.1/joda-time-2.8.1.jar'
15
+ require 'software/amazon/ion/ion-java/1.0.2/ion-java-1.0.2.jar'
16
+ require 'com/amazonaws/amazon-kinesis-client/1.9.2/amazon-kinesis-client-1.9.2.jar'
17
+ require 'com/amazonaws/aws-java-sdk-kinesis/1.11.400/aws-java-sdk-kinesis-1.11.400.jar'
18
+ require 'com/amazonaws/aws-java-sdk-cloudwatch/1.11.400/aws-java-sdk-cloudwatch-1.11.400.jar'
19
+ require 'org/apache/httpcomponents/httpcore/4.4.9/httpcore-4.4.9.jar'
20
+ require 'com/amazonaws/aws-java-sdk-dynamodb/1.11.400/aws-java-sdk-dynamodb-1.11.400.jar'
21
+ require 'com/amazonaws/aws-java-sdk-core/1.11.414/aws-java-sdk-core-1.11.414.jar'
22
+ require 'commons-codec/commons-codec/1.10/commons-codec-1.10.jar'
23
+ require 'com/fasterxml/jackson/core/jackson-annotations/2.6.0/jackson-annotations-2.6.0.jar'
24
+ require 'com/amazonaws/aws-java-sdk-kms/1.11.400/aws-java-sdk-kms-1.11.400.jar'
25
+ require 'com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.jar'
26
+ end
27
+
28
+ if defined? Jars
29
+ require_jar 'com.fasterxml.jackson.core', 'jackson-databind', '2.6.7.1'
30
+ require_jar 'com.fasterxml.jackson.core', 'jackson-core', '2.6.7'
31
+ require_jar 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-cbor', '2.6.7'
32
+ require_jar 'org.apache.httpcomponents', 'httpclient', '4.5.5'
33
+ require_jar 'com.amazonaws', 'jmespath-java', '1.11.400'
34
+ require_jar 'com.amazonaws', 'aws-java-sdk-s3', '1.11.400'
35
+ require_jar 'com.google.guava', 'guava', '18.0'
36
+ require_jar 'commons-lang', 'commons-lang', '2.6'
37
+ require_jar 'commons-logging', 'commons-logging', '1.1.3'
38
+ require_jar 'joda-time', 'joda-time', '2.8.1'
39
+ require_jar 'software.amazon.ion', 'ion-java', '1.0.2'
40
+ require_jar 'com.amazonaws', 'amazon-kinesis-client', '1.9.2'
41
+ require_jar 'com.amazonaws', 'aws-java-sdk-kinesis', '1.11.400'
42
+ require_jar 'com.amazonaws', 'aws-java-sdk-cloudwatch', '1.11.400'
43
+ require_jar 'org.apache.httpcomponents', 'httpcore', '4.4.9'
44
+ require_jar 'com.amazonaws', 'aws-java-sdk-dynamodb', '1.11.400'
45
+ require_jar 'com.amazonaws', 'aws-java-sdk-core', '1.11.414'
46
+ require_jar 'commons-codec', 'commons-codec', '1.10'
47
+ require_jar 'com.fasterxml.jackson.core', 'jackson-annotations', '2.6.0'
48
+ require_jar 'com.amazonaws', 'aws-java-sdk-kms', '1.11.400'
49
+ require_jar 'com.google.protobuf', 'protobuf-java', '2.6.1'
50
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-input-kinesis-jordanforks
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.9
5
+ platform: java
6
+ authors:
7
+ - Brian Palmer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-10-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash-core-plugin-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '1.60'
20
+ - - <=
21
+ - !ruby/object:Gem::Version
22
+ version: '2.99'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '1.60'
30
+ - - <=
31
+ - !ruby/object:Gem::Version
32
+ version: '2.99'
33
+ - !ruby/object:Gem::Dependency
34
+ name: logstash-devutils
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: jar-dependencies
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.3.4
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: 0.3.4
61
+ - !ruby/object:Gem::Dependency
62
+ name: logstash-codec-json
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ description: This gem is a logstash plugin required to be installed on top of the
76
+ Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not
77
+ a stand-alone program
78
+ email:
79
+ - brian@codekitchen.net
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - lib/logstash/inputs/kinesis/version.rb
85
+ - lib/logstash/inputs/kinesis/worker.rb
86
+ - lib/logstash/inputs/kinesis.rb
87
+ - spec/inputs/kinesis/worker_spec.rb
88
+ - spec/inputs/kinesis_spec.rb
89
+ - spec/spec_helper.rb
90
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/amazon-kinesis-client/1.9.2/amazon-kinesis-client-1.9.2.jar
91
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-cloudwatch/1.11.400/aws-java-sdk-cloudwatch-1.11.400.jar
92
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-core/1.11.414/aws-java-sdk-core-1.11.414.jar
93
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-dynamodb/1.11.400/aws-java-sdk-dynamodb-1.11.400.jar
94
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-kinesis/1.11.400/aws-java-sdk-kinesis-1.11.400.jar
95
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-kms/1.11.400/aws-java-sdk-kms-1.11.400.jar
96
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/aws-java-sdk-s3/1.11.400/aws-java-sdk-s3-1.11.400.jar
97
+ - vendor/jar-dependencies/runtime-jars/com/amazonaws/jmespath-java/1.11.400/jmespath-java-1.11.400.jar
98
+ - vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/core/jackson-annotations/2.6.0/jackson-annotations-2.6.0.jar
99
+ - vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/core/jackson-core/2.6.7/jackson-core-2.6.7.jar
100
+ - vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/core/jackson-databind/2.6.7.1/jackson-databind-2.6.7.1.jar
101
+ - vendor/jar-dependencies/runtime-jars/com/fasterxml/jackson/dataformat/jackson-dataformat-cbor/2.6.7/jackson-dataformat-cbor-2.6.7.jar
102
+ - vendor/jar-dependencies/runtime-jars/com/google/guava/guava/18.0/guava-18.0.jar
103
+ - vendor/jar-dependencies/runtime-jars/com/google/protobuf/protobuf-java/2.6.1/protobuf-java-2.6.1.jar
104
+ - vendor/jar-dependencies/runtime-jars/commons-codec/commons-codec/1.10/commons-codec-1.10.jar
105
+ - vendor/jar-dependencies/runtime-jars/commons-lang/commons-lang/2.6/commons-lang-2.6.jar
106
+ - vendor/jar-dependencies/runtime-jars/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar
107
+ - vendor/jar-dependencies/runtime-jars/joda-time/joda-time/2.8.1/joda-time-2.8.1.jar
108
+ - vendor/jar-dependencies/runtime-jars/logstash-input-kinesis-jordanforks_jars.rb
109
+ - vendor/jar-dependencies/runtime-jars/org/apache/httpcomponents/httpclient/4.5.5/httpclient-4.5.5.jar
110
+ - vendor/jar-dependencies/runtime-jars/org/apache/httpcomponents/httpcore/4.4.9/httpcore-4.4.9.jar
111
+ - vendor/jar-dependencies/runtime-jars/software/amazon/ion/ion-java/1.0.2/ion-java-1.0.2.jar
112
+ - logstash-input-kinesis.gemspec
113
+ - CHANGELOG.md
114
+ - README.md
115
+ - CONTRIBUTORS
116
+ - Gemfile
117
+ homepage: https://github.com/logstash-plugins/logstash-input-kinesis
118
+ licenses:
119
+ - Apache-2.0
120
+ metadata:
121
+ logstash_plugin: 'true'
122
+ logstash_group: input
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ - vendor/jar-dependencies/runtime-jars
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements:
139
+ - jar 'com.amazonaws:amazon-kinesis-client', '1.9.2'
140
+ - jar 'com.amazonaws:aws-java-sdk-core', '1.11.414'
141
+ rubyforge_project:
142
+ rubygems_version: 2.0.14.1
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Receives events through an AWS Kinesis stream
146
+ test_files:
147
+ - spec/inputs/kinesis/worker_spec.rb
148
+ - spec/inputs/kinesis_spec.rb
149
+ - spec/spec_helper.rb