logstash-input-kinesis-jordanforks 2.0.9-java

Sign up to get free protection for your applications and to get access to all the features.
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