logstash-input-rabbitmq 0.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ODdmYmIwZDg5ZGFiZmMxZGExNGE3MmM2M2RmODRhODg3MTJkNDhkMQ==
5
- data.tar.gz: !binary |-
6
- ZDlmNDIzZGY3Y2NmOWFlMTlhMzQ5ZDk5MjQxMTM0NTJmMDA2MDBlYw==
2
+ SHA1:
3
+ metadata.gz: 63863bf744b2904baccd696f14968c741d858e30
4
+ data.tar.gz: 630d4a3870e93baa41363675c2f79a3a7467a866
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- OTU1NGViZTA0Y2NhNmVkNGZhZTE3ZDVkZmVkN2RlZmVhYzMyMjBkMjNlMzUy
10
- OWVkZTAwMWMxZDdiNjAxZjJmMGNhNGMzN2E3MzQyZTdhNzhkYjhkMDFkZTlj
11
- ZWM3MTQyOTU5NWZjYjE2M2JkZGIyMTBjNDBjYTM5Y2M5NGViOTY=
12
- data.tar.gz: !binary |-
13
- YzllMjI4NzNlZDJmMmI4MTk1OTM1N2UxNzVmNjhjYjNiNzQwNWE4ZmMwMDZk
14
- YmM4NjUxN2MyMmExYWUwOWY1MDY3Yjk2MDllZWE3MjA3MzE5OGZhMTlmN2E2
15
- NjRhNTdmYmYwOWJhYzZjMDM1MTkyNzVhMDQwNjliMTRjYWU3MWU=
6
+ metadata.gz: 502452f178e270279701933abb79859fcb65c28b49c6ff919104a3d7d549e4d0a4355f127b06d9f9c33fdf19c60621b45911d161390958a382a69b61e209b565
7
+ data.tar.gz: 6e9d1da9c818443681c60ea116bf1fbe6d20cbc7015ae7425935a8d9fac1006e0ede54ed40e49a1770b486ec1a7fb438b08636e704b92cd0849d718b77523b78
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ * 2.0.0
2
+ - Massive refactor
3
+ - Implement Logstash 2.x stop behavior
4
+ - Fix reconnect issues
5
+ - Depend on rabbitmq_connection mixin for most connection functionality
6
+ * 1.1.1
7
+ - Bump march hare to 2.12.0 which fixes jar perms on unices
8
+ * 1.1.0
9
+ - Bump march hare version to 2.11.0
data/CONTRIBUTORS ADDED
@@ -0,0 +1,22 @@
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
+ Contributors:
5
+ * Avishai Ish-Shalom (avishai-ish-shalom)
6
+ * Jonathan Van Eenwyk (jdve)
7
+ * Jordan Sissel (jordansissel)
8
+ * João Duarte (jsvd)
9
+ * Mathieu MILLET (htam-net)
10
+ * Michael Klishin (michaelklishin)
11
+ * Michael Zaccari (mzaccari)
12
+ * Nick Ethier (nickethier)
13
+ * Pier-Hugues Pellerin (ph)
14
+ * Richard Pijnenburg (electrical)
15
+ * Suyog Rao (suyograo)
16
+ * Tim Potter (tpot)
17
+ * avleen
18
+
19
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
20
+ Logstash, and you aren't on the list above and want to be, please let us know
21
+ and we'll make sure you're here. Contributions from folks like you are what make
22
+ open source awesome.
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
- source 'http://rubygems.org'
2
- gem 'rake'
3
- gem 'gem_publisher'
4
- gem 'archive-tar-minitar'
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2014 Elasticsearch <http://www.elasticsearch.org>
1
+ Copyright (c) 2012–2015 Elasticsearch <http://www.elastic.co>
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
data/NOTICE.TXT ADDED
@@ -0,0 +1,5 @@
1
+ Elasticsearch
2
+ Copyright 2012-2015 Elasticsearch
3
+
4
+ This product includes software developed by The Apache Software
5
+ Foundation (http://www.apache.org/).
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # Logstash Plugin
2
+
3
+ This is a plugin for [Logstash](https://github.com/elastic/logstash).
4
+
5
+ It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
6
+
7
+ ## Documentation
8
+
9
+ Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elastic.co/guide/en/logstash/current/).
10
+
11
+ - For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
12
+ - For more asciidoc formatting tips, see the excellent reference here https://github.com/elastic/docs#asciidoc-guide
13
+
14
+ ## Need Help?
15
+
16
+ Need help? Try #logstash on freenode IRC or the https://discuss.elastic.co/c/logstash discussion forum.
17
+
18
+ ## Developing
19
+
20
+ ### 1. Plugin Developement and Testing
21
+
22
+ #### Code
23
+ - To get started, you'll need JRuby with the Bundler gem installed.
24
+
25
+ - Create a new plugin or clone and existing from the GitHub [logstash-plugins](https://github.com/logstash-plugins) organization. We also provide [example plugins](https://github.com/logstash-plugins?query=example).
26
+
27
+ - Install dependencies
28
+ ```sh
29
+ bundle install
30
+ ```
31
+
32
+ #### Test
33
+
34
+ - Update your dependencies
35
+
36
+ ```sh
37
+ bundle install
38
+ ```
39
+
40
+ - Run tests
41
+
42
+ ```sh
43
+ bundle exec rspec
44
+ ```
45
+
46
+ ### 2. Running your unpublished Plugin in Logstash
47
+
48
+ #### 2.1 Run in a local Logstash clone
49
+
50
+ - Edit Logstash `Gemfile` and add the local plugin path, for example:
51
+ ```ruby
52
+ gem "logstash-filter-awesome", :path => "/your/local/logstash-filter-awesome"
53
+ ```
54
+ - Install plugin
55
+ ```sh
56
+ bin/plugin install --no-verify
57
+ ```
58
+ - Run Logstash with your plugin
59
+ ```sh
60
+ bin/logstash -e 'filter {awesome {}}'
61
+ ```
62
+ At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
63
+
64
+ #### 2.2 Run in an installed Logstash
65
+
66
+ You can use the same **2.1** method to run your plugin in an installed Logstash by editing its `Gemfile` and pointing the `:path` to your local plugin development directory or you can build the gem and install it using:
67
+
68
+ - Build your plugin gem
69
+ ```sh
70
+ gem build logstash-filter-awesome.gemspec
71
+ ```
72
+ - Install the plugin from the Logstash home
73
+ ```sh
74
+ bin/plugin install /your/local/plugin/logstash-filter-awesome.gem
75
+ ```
76
+ - Start Logstash and proceed to test the plugin
77
+
78
+ ## Contributing
79
+
80
+ All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
81
+
82
+ Programming is not a required skill. Whatever you've seen about open source and maintainers or community members saying "send patches or die" - you will not see that here.
83
+
84
+ It is more important to the community that you are able to contribute.
85
+
86
+ For more information about contributing, see the [CONTRIBUTING](https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md) file.
@@ -1,128 +1,111 @@
1
1
  # encoding: utf-8
2
- require "logstash/inputs/threadable"
3
- require "logstash/namespace"
4
-
5
- # Pull events from a RabbitMQ exchange.
6
- #
7
- # The default settings will create an entirely transient queue and listen for all messages by default.
8
- # If you need durability or any other advanced settings, please set the appropriate options
9
- #
10
- # This has been tested with Bunny 0.9.x, which supports RabbitMQ 2.x and 3.x. You can
11
- # find links to both here:
12
- #
13
- # * RabbitMQ - <http://www.rabbitmq.com/>
14
- # * March Hare: <http://rubymarchhare.info>
15
- # * Bunny - <https://github.com/ruby-amqp/bunny>
16
- class LogStash::Inputs::RabbitMQ < LogStash::Inputs::Threadable
17
-
18
- config_name "rabbitmq"
19
- milestone 1
20
-
21
- #
22
- # Connection
23
- #
24
-
25
- # RabbitMQ server address
26
- config :host, :validate => :string, :required => true
27
-
28
- # RabbitMQ port to connect on
29
- config :port, :validate => :number, :default => 5672
30
-
31
- # RabbitMQ username
32
- config :user, :validate => :string, :default => "guest"
33
-
34
- # RabbitMQ password
35
- config :password, :validate => :password, :default => "guest"
36
-
37
- # The vhost to use. If you don't know what this is, leave the default.
38
- config :vhost, :validate => :string, :default => "/"
39
-
40
- # Enable or disable SSL
41
- config :ssl, :validate => :boolean, :default => false
42
-
43
- # Validate SSL certificate
44
- config :verify_ssl, :validate => :boolean, :default => false
45
-
46
- # Enable or disable logging
47
- config :debug, :validate => :boolean, :default => false, :deprecated => "Use the logstash --debug flag for this instead."
48
-
49
-
50
-
51
- #
52
- # Queue & Consumer
53
- #
54
-
55
- # The name of the queue Logstash will consume events from.
56
- config :queue, :validate => :string, :default => ""
57
-
58
- # Is this queue durable? (aka; Should it survive a broker restart?)
59
- config :durable, :validate => :boolean, :default => false
60
-
61
- # Should the queue be deleted on the broker when the last consumer
62
- # disconnects? Set this option to 'false' if you want the queue to remain
63
- # on the broker, queueing up messages until a consumer comes along to
64
- # consume them.
65
- config :auto_delete, :validate => :boolean, :default => false
66
-
67
- # Is the queue exclusive? Exclusive queues can only be used by the connection
68
- # that declared them and will be deleted when it is closed (e.g. due to a Logstash
69
- # restart).
70
- config :exclusive, :validate => :boolean, :default => false
71
-
72
- # Extra queue arguments as an array.
73
- # To make a RabbitMQ queue mirrored, use: {"x-ha-policy" => "all"}
74
- config :arguments, :validate => :array, :default => {}
75
-
76
- # Prefetch count. Number of messages to prefetch
77
- config :prefetch_count, :validate => :number, :default => 256
78
-
79
- # Enable message acknowledgement
80
- config :ack, :validate => :boolean, :default => true
81
-
82
- # Passive queue creation? Useful for checking queue existance without modifying server state
83
- config :passive, :validate => :boolean, :default => false
84
-
85
-
86
-
87
- #
88
- # (Optional) Exchange binding
89
- #
90
-
91
- # Optional.
92
- #
93
- # The name of the exchange to bind the queue to.
94
- config :exchange, :validate => :string
95
-
96
- # Optional.
97
- #
98
- # The routing key to use when binding a queue to the exchange.
99
- # This is only relevant for direct or topic exchanges.
100
- #
101
- # * Routing keys are ignored on fanout exchanges.
102
- # * Wildcards are not valid on direct exchanges.
103
- config :key, :validate => :string, :default => "logstash"
104
-
105
-
106
- def initialize(params)
107
- params["codec"] = "json" if !params["codec"]
108
-
109
- super
110
- end
111
-
112
- # Use March Hare on JRuby to avoid IO#select CPU spikes
113
- # (see github.com/ruby-amqp/bunny/issues/95).
114
- #
115
- # On MRI, use Bunny.
116
- #
117
- # See http://rubybunny.info and http://rubymarchhare.info
118
- # for the docs.
119
- if RUBY_ENGINE == "jruby"
120
- require "logstash/inputs/rabbitmq/march_hare"
121
-
122
- include MarchHareImpl
123
- else
124
- require "logstash/inputs/rabbitmq/bunny"
125
-
126
- include BunnyImpl
2
+ require 'logstash/plugin_mixins/rabbitmq_connection'
3
+ require 'logstash/inputs/threadable'
4
+
5
+ module LogStash
6
+ module Inputs
7
+ class RabbitMQ < LogStash::Inputs::Threadable
8
+ include ::LogStash::PluginMixins::RabbitMQConnection
9
+
10
+ config_name("rabbitmq")
11
+
12
+ # The name of the queue Logstash will consume events from.
13
+ config :queue, :validate => :string, :default => ""
14
+
15
+ # Is this queue durable? (aka; Should it survive a broker restart?)
16
+ config :durable, :validate => :boolean, :default => false
17
+
18
+ # Should the queue be deleted on the broker when the last consumer
19
+ # disconnects? Set this option to `false` if you want the queue to remain
20
+ # on the broker, queueing up messages until a consumer comes along to
21
+ # consume them.
22
+ config :auto_delete, :validate => :boolean, :default => false
23
+
24
+ # Is the queue exclusive? Exclusive queues can only be used by the connection
25
+ # that declared them and will be deleted when it is closed (e.g. due to a Logstash
26
+ # restart).
27
+ config :exclusive, :validate => :boolean, :default => false
28
+
29
+ # Extra queue arguments as an array.
30
+ # To make a RabbitMQ queue mirrored, use: `{"x-ha-policy" => "all"}`
31
+ config :arguments, :validate => :array, :default => {}
32
+
33
+ # Prefetch count. Number of messages to prefetch
34
+ config :prefetch_count, :validate => :number, :default => 256
35
+
36
+ # Enable message acknowledgement
37
+ config :ack, :validate => :boolean, :default => true
38
+
39
+ # Passive queue creation? Useful for checking queue existance without modifying server state
40
+ config :passive, :validate => :boolean, :default => false
41
+
42
+ # The name of the exchange to bind the queue to
43
+ config :exchange, :validate => :string
44
+
45
+ # The routing key to use when binding a queue to the exchange.
46
+ # This is only relevant for direct or topic exchanges.
47
+ #
48
+ # * Routing keys are ignored on fanout exchanges.
49
+ # * Wildcards are not valid on direct exchanges.
50
+ config :key, :validate => :string, :default => "logstash"
51
+
52
+
53
+ def register
54
+ connect!
55
+
56
+ declare_queue!
57
+ bind_exchange!
58
+ end
59
+
60
+ def run(output_queue)
61
+ @output_queue = output_queue
62
+ consume!
63
+ end
64
+
65
+ def bind_exchange!
66
+ if @exchange
67
+ @hare_info.queue.bind(@exchange, :routing_key => @key)
68
+ end
69
+ end
70
+
71
+ def declare_queue!
72
+ @hare_info.queue = declare_queue()
73
+ end
74
+
75
+ def declare_queue
76
+ @hare_info.channel.queue(@queue,
77
+ :durable => @durable,
78
+ :auto_delete => @auto_delete,
79
+ :exclusive => @exclusive,
80
+ :passive => @passive,
81
+ :arguments => @arguments)
82
+ end
83
+
84
+ def consume!
85
+ # we manually build a consumer here to be able to keep a reference to it
86
+ # in an @ivar even though we use a blocking version of HB::Queue#subscribe
87
+ @consumer = @hare_info.queue.build_consumer(:block => true) do |metadata, data|
88
+ @codec.decode(data) do |event|
89
+ decorate(event)
90
+ @output_queue << event if event
91
+ end
92
+ @hare_info.channel.ack(metadata.delivery_tag) if @ack
93
+ end
94
+
95
+ @hare_info.queue.subscribe_with(@consumer, :manual_ack => @ack, :block => true)
96
+ end
97
+
98
+ def stop
99
+ super
100
+ shutdown_consumer
101
+ close_connection
102
+ end
103
+
104
+ def shutdown_consumer
105
+ return unless @consumer
106
+ @consumer.gracefully_shut_down
107
+ end
108
+
109
+ end
127
110
  end
128
- end # class LogStash::Inputs::RabbitMQ
111
+ end
@@ -1,34 +1,30 @@
1
1
  Gem::Specification.new do |s|
2
-
3
2
  s.name = 'logstash-input-rabbitmq'
4
- s.version = '0.1.0'
3
+ s.version = '3.0.0'
5
4
  s.licenses = ['Apache License (2.0)']
6
5
  s.summary = "Pull events from a RabbitMQ exchange."
7
- s.description = "Pull events from a RabbitMQ exchange."
8
- s.authors = ["Elasticsearch"]
9
- s.email = 'richard.pijnenburg@elasticsearch.com'
10
- s.homepage = "http://logstash.net/"
6
+ s.description = "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"
7
+ s.authors = ["Elastic"]
8
+ s.email = 'info@elastic.co'
9
+ s.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
11
10
  s.require_paths = ["lib"]
12
11
 
13
12
  # Files
14
- s.files = `git ls-files`.split($\)+::Dir.glob('vendor/*')
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
15
14
 
16
15
  # Tests
17
16
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
17
 
19
18
  # Special flag to let us know this is actually a logstash plugin
20
- s.metadata = { "logstash_plugin" => "true", "group" => "input" }
19
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
21
20
 
22
21
  # Gem dependencies
23
- s.add_runtime_dependency 'logstash', '>= 1.4.0', '< 2.0.0'
22
+ s.add_runtime_dependency "logstash-core", "~> 2.0.0.snapshot"
23
+ s.add_runtime_dependency "logstash-mixin-rabbitmq_connection", '>= 1.0.0', '< 2.0.0'
24
24
 
25
25
  s.add_runtime_dependency 'logstash-codec-json'
26
26
 
27
- if RUBY_PLATFORM == 'java'
28
- s.add_runtime_dependency 'march_hare', ['~> 2.5.1']
29
- else
30
- s.add_runtime_dependency 'bunny', ['>= 1.6.0']
31
- end
32
-
27
+ s.add_development_dependency 'logstash-devutils'
28
+ s.add_development_dependency 'logstash-codec-plain'
33
29
  end
34
30
 
@@ -1 +1,132 @@
1
- require 'spec_helper'
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/inputs/rabbitmq"
4
+ require "thread"
5
+
6
+ Thread.abort_on_exception = true
7
+
8
+ describe LogStash::Inputs::RabbitMQ do
9
+ let(:klass) { LogStash::Inputs::RabbitMQ }
10
+ let(:host) { "localhost" }
11
+ let(:port) { 5672 }
12
+ let(:exchange_type) { "topic" }
13
+ let(:exchange) { "myexchange" }
14
+ let(:queue) { "myqueue" }
15
+ let(:rabbitmq_settings) {
16
+ {
17
+ "host" => host,
18
+ "port" => port,
19
+ "queue" => queue
20
+ }
21
+ }
22
+ let(:instance) { klass.new(rabbitmq_settings) }
23
+ let(:hare_info) { instance.instance_variable_get(:@hare_info) }
24
+
25
+ context "when connected" do
26
+ let(:connection) { double("MarchHare Connection") }
27
+ let(:channel) { double("Channel") }
28
+ let(:exchange) { double("Exchange") }
29
+ let(:channel) { double("Channel") }
30
+ let(:queue) { double("queue") }
31
+
32
+ before do
33
+ allow(instance).to receive(:connect!).and_call_original
34
+ allow(::MarchHare).to receive(:connect).and_return(connection)
35
+ allow(connection).to receive(:create_channel).and_return(channel)
36
+ allow(connection).to receive(:on_blocked)
37
+ allow(connection).to receive(:on_unblocked)
38
+ allow(channel).to receive(:exchange).and_return(exchange)
39
+ allow(channel).to receive(:queue).and_return(queue)
40
+
41
+ allow(queue).to receive(:build_consumer).with(:block => true)
42
+ allow(queue).to receive(:subscribe_with).with(any_args)
43
+
44
+ instance.register
45
+ end
46
+
47
+ describe "#connect!" do
48
+ subject { hare_info }
49
+
50
+ it "should set the queue correctly" do
51
+ expect(subject.queue).to eql(queue)
52
+ end
53
+
54
+ context "with an exchange declared" do
55
+ let(:instance) { rabbitmq_settings.merge("exchange" => "myexchange", "exchange_type" => "fanout") }
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ describe "with a live server", :integration => true do
62
+ let(:klass) { LogStash::Inputs::RabbitMQ }
63
+ let(:config) { {"host" => "127.0.0.1"} }
64
+ let(:instance) { klass.new(config) }
65
+ let(:hare_info) { instance.instance_variable_get(:@hare_info) }
66
+ let(:output_queue) { Queue.new }
67
+
68
+ # Spawn a connection in the bg and wait up (n) seconds
69
+ def spawn_and_wait(instance)
70
+ instance.register
71
+
72
+ output_queue # materialize in this thread
73
+
74
+ Thread.new {
75
+ instance.run(output_queue)
76
+ }
77
+
78
+ 20.times do
79
+ instance.connected? ? break : sleep(0.1)
80
+ end
81
+
82
+ # Extra time to make sure the consumer can attach
83
+ # Without this there's a chance the shutdown code will execute
84
+ # before consumption begins. This is tricky to do more elegantly
85
+ sleep 1
86
+ end
87
+
88
+ let(:test_connection) { MarchHare.connect(instance.send(:rabbitmq_settings)) }
89
+ let(:test_channel) { test_connection.create_channel }
90
+
91
+ before do
92
+ # Materialize the instance in the current thread to prevent dupes
93
+ # If you use multiple threads with lazy evaluation weird stuff happens
94
+ instance
95
+ spawn_and_wait(instance)
96
+
97
+ test_channel # Start up the test client as well
98
+ end
99
+
100
+ after do
101
+ instance.stop()
102
+ test_channel.close
103
+ test_connection.close
104
+ end
105
+
106
+ context "using defaults" do
107
+ it "should start, connect, and stop cleanly" do
108
+ expect(instance.connected?).to be_truthy
109
+ end
110
+ end
111
+
112
+ describe "receiving a message with a queue specified" do
113
+ let(:queue_name) { "foo_queue" }
114
+ let(:config) { super.merge("queue" => queue_name) }
115
+
116
+ it "should process the message" do
117
+ message = "Foo Message"
118
+ q = test_channel.queue(queue_name)
119
+ q.publish(message)
120
+
121
+ event = output_queue.pop
122
+ expect(event["message"]).to eql(message)
123
+ end
124
+ end
125
+
126
+ describe LogStash::Inputs::RabbitMQ do
127
+ let(:config) { super.merge("queue" => "foo_queue") }
128
+ it_behaves_like "an interruptible input plugin" do
129
+
130
+ end
131
+ end
132
+ end
metadata CHANGED
@@ -1,105 +1,130 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-rabbitmq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Elasticsearch
8
- autorequire:
7
+ - Elastic
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-05 00:00:00.000000000 Z
11
+ date: 2015-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: logstash
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - ! '>='
16
+ - - ~>
18
17
  - !ruby/object:Gem::Version
19
- version: 1.4.0
18
+ version: 2.0.0.snapshot
19
+ name: logstash-core
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0.snapshot
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.0
20
33
  - - <
21
34
  - !ruby/object:Gem::Version
22
35
  version: 2.0.0
23
- type: :runtime
36
+ name: logstash-mixin-rabbitmq_connection
24
37
  prerelease: false
38
+ type: :runtime
25
39
  version_requirements: !ruby/object:Gem::Requirement
26
40
  requirements:
27
- - - ! '>='
41
+ - - '>='
28
42
  - !ruby/object:Gem::Version
29
- version: 1.4.0
43
+ version: 1.0.0
30
44
  - - <
31
45
  - !ruby/object:Gem::Version
32
46
  version: 2.0.0
33
47
  - !ruby/object:Gem::Dependency
34
- name: logstash-codec-json
35
48
  requirement: !ruby/object:Gem::Requirement
36
49
  requirements:
37
- - - ! '>='
50
+ - - '>='
38
51
  - !ruby/object:Gem::Version
39
52
  version: '0'
53
+ name: logstash-codec-json
54
+ prerelease: false
40
55
  type: :runtime
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ name: logstash-devutils
41
68
  prerelease: false
69
+ type: :development
42
70
  version_requirements: !ruby/object:Gem::Requirement
43
71
  requirements:
44
- - - ! '>='
72
+ - - '>='
45
73
  - !ruby/object:Gem::Version
46
74
  version: '0'
47
75
  - !ruby/object:Gem::Dependency
48
- name: bunny
49
76
  requirement: !ruby/object:Gem::Requirement
50
77
  requirements:
51
- - - ! '>='
78
+ - - '>='
52
79
  - !ruby/object:Gem::Version
53
- version: 1.6.0
54
- type: :runtime
80
+ version: '0'
81
+ name: logstash-codec-plain
55
82
  prerelease: false
83
+ type: :development
56
84
  version_requirements: !ruby/object:Gem::Requirement
57
85
  requirements:
58
- - - ! '>='
86
+ - - '>='
59
87
  - !ruby/object:Gem::Version
60
- version: 1.6.0
61
- description: Pull events from a RabbitMQ exchange.
62
- email: richard.pijnenburg@elasticsearch.com
88
+ version: '0'
89
+ description: 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
90
+ email: info@elastic.co
63
91
  executables: []
64
92
  extensions: []
65
93
  extra_rdoc_files: []
66
94
  files:
67
- - .gitignore
95
+ - CHANGELOG.md
96
+ - CONTRIBUTORS
68
97
  - Gemfile
69
98
  - LICENSE
70
- - Rakefile
99
+ - NOTICE.TXT
100
+ - README.md
71
101
  - lib/logstash/inputs/rabbitmq.rb
72
- - lib/logstash/inputs/rabbitmq/bunny.rb
73
- - lib/logstash/inputs/rabbitmq/hot_bunnies.rb
74
- - lib/logstash/inputs/rabbitmq/march_hare.rb
75
102
  - logstash-input-rabbitmq.gemspec
76
- - rakelib/publish.rake
77
- - rakelib/vendor.rake
78
103
  - spec/inputs/rabbitmq_spec.rb
79
- homepage: http://logstash.net/
104
+ homepage: http://www.elastic.co/guide/en/logstash/current/index.html
80
105
  licenses:
81
106
  - Apache License (2.0)
82
107
  metadata:
83
108
  logstash_plugin: 'true'
84
- group: input
85
- post_install_message:
109
+ logstash_group: input
110
+ post_install_message:
86
111
  rdoc_options: []
87
112
  require_paths:
88
113
  - lib
89
114
  required_ruby_version: !ruby/object:Gem::Requirement
90
115
  requirements:
91
- - - ! '>='
116
+ - - '>='
92
117
  - !ruby/object:Gem::Version
93
118
  version: '0'
94
119
  required_rubygems_version: !ruby/object:Gem::Requirement
95
120
  requirements:
96
- - - ! '>='
121
+ - - '>='
97
122
  - !ruby/object:Gem::Version
98
123
  version: '0'
99
124
  requirements: []
100
- rubyforge_project:
101
- rubygems_version: 2.4.1
102
- signing_key:
125
+ rubyforge_project:
126
+ rubygems_version: 2.4.8
127
+ signing_key:
103
128
  specification_version: 4
104
129
  summary: Pull events from a RabbitMQ exchange.
105
130
  test_files:
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- *.gem
2
- Gemfile.lock
3
- .bundle
4
- vendor
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- @files=[]
2
-
3
- task :default do
4
- system("rake -T")
5
- end
6
-
@@ -1,118 +0,0 @@
1
- # encoding: utf-8
2
- class LogStash::Inputs::RabbitMQ
3
- module BunnyImpl
4
- def register
5
- require "bunny"
6
-
7
- @vhost ||= Bunny::DEFAULT_HOST
8
- # 5672. Will be switched to 5671 by Bunny if TLS is enabled.
9
- @port ||= AMQ::Protocol::DEFAULT_PORT
10
- @routing_key ||= "#"
11
-
12
- @settings = {
13
- :vhost => @vhost,
14
- :host => @host,
15
- :port => @port,
16
- :automatically_recover => false
17
- }
18
- @settings[:user] = @user || Bunny::DEFAULT_USER
19
- @settings[:pass] = if @password
20
- @password.value
21
- else
22
- Bunny::DEFAULT_PASSWORD
23
- end
24
-
25
- @settings[:log_level] = if @debug || @logger.debug?
26
- :debug
27
- else
28
- :error
29
- end
30
-
31
- @settings[:tls] = @ssl if @ssl
32
- @settings[:verify_ssl] = @verify_ssl if @verify_ssl
33
-
34
- proto = if @ssl
35
- "amqps"
36
- else
37
- "amqp"
38
- end
39
- @connection_url = "#{proto}://#{@user}@#{@host}:#{@port}#{vhost}/#{@queue}"
40
-
41
- @logger.info("Registering input #{@connection_url}")
42
- end
43
-
44
- def run(output_queue)
45
- @output_queue = output_queue
46
-
47
- begin
48
- setup
49
- consume
50
- rescue Bunny::NetworkFailure, Bunny::ConnectionClosedError, Bunny::ConnectionLevelException, Bunny::TCPConnectionFailed => e
51
- n = Bunny::Session::DEFAULT_NETWORK_RECOVERY_INTERVAL * 2
52
-
53
- # Because we manually reconnect instead of letting Bunny
54
- # handle failures,
55
- # make sure we don't leave any consumer work pool
56
- # threads behind. MK.
57
- @ch.maybe_kill_consumer_work_pool!
58
- @logger.error("RabbitMQ connection error: #{e.message}. Will attempt to reconnect in #{n} seconds...")
59
-
60
- sleep n
61
- retry
62
- end
63
- end
64
-
65
- def teardown
66
- @consumer.cancel
67
-
68
- @ch.close if @ch && @ch.open?
69
- @conn.close if @conn && @conn.open?
70
-
71
- finished
72
- end
73
-
74
- def setup
75
- @conn = Bunny.new(@settings)
76
-
77
- @logger.debug("Connecting to RabbitMQ. Settings: #{@settings.inspect}, queue: #{@queue.inspect}")
78
- return if terminating?
79
- @conn.start
80
-
81
- @ch = @conn.create_channel.tap do |ch|
82
- ch.prefetch(@prefetch_count)
83
- end
84
- @logger.info("Connected to RabbitMQ at #{@settings[:host]}")
85
-
86
- @arguments_hash = Hash[*@arguments]
87
-
88
- @q = @ch.queue(@queue,
89
- :durable => @durable,
90
- :auto_delete => @auto_delete,
91
- :exclusive => @exclusive,
92
- :passive => @passive,
93
- :arguments => @arguments)
94
-
95
- # exchange binding is optional for the input
96
- if @exchange
97
- @q.bind(@exchange, :routing_key => @key)
98
- end
99
- end
100
-
101
- def consume
102
- @logger.info("Will consume events from queue #{@q.name}")
103
-
104
- # we both need to block the caller in Bunny::Queue#subscribe and have
105
- # a reference to the consumer so that we can cancel it, so
106
- # a consumer manually. MK.
107
- @consumer = Bunny::Consumer.new(@ch, @q)
108
- @q.subscribe(:manual_ack => @ack, :block => true) do |delivery_info, properties, data|
109
- @codec.decode(data) do |event|
110
- decorate(event)
111
- @output_queue << event
112
- end
113
-
114
- @ch.acknowledge(delivery_info.delivery_tag) if @ack
115
- end
116
- end
117
- end # BunnyImpl
118
- end
@@ -1 +0,0 @@
1
- require "logstash/inputs/rabbitmq/march_hare"
@@ -1,129 +0,0 @@
1
- # encoding: utf-8
2
- class LogStash::Inputs::RabbitMQ
3
- # MarchHare-based implementation for JRuby
4
- module MarchHareImpl
5
- def register
6
- require "hot_bunnies"
7
- require "java"
8
-
9
- @vhost ||= "127.0.0.1"
10
- # 5672. Will be switched to 5671 by Bunny if TLS is enabled.
11
- @port ||= 5672
12
- @key ||= "#"
13
-
14
- @settings = {
15
- :vhost => @vhost,
16
- :host => @host,
17
- :port => @port,
18
- :user => @user,
19
- :automatic_recovery => false
20
- }
21
- @settings[:pass] = @password.value if @password
22
- @settings[:tls] = @ssl if @ssl
23
-
24
- proto = if @ssl
25
- "amqps"
26
- else
27
- "amqp"
28
- end
29
- @connection_url = "#{proto}://#{@user}@#{@host}:#{@port}#{vhost}/#{@queue}"
30
-
31
- @logger.info("Registering input #{@connection_url}")
32
- end
33
-
34
- def run(output_queue)
35
- @output_queue = output_queue
36
- @break_out_of_the_loop = java.util.concurrent.atomic.AtomicBoolean.new(false)
37
-
38
- # MarchHare does not raise exceptions when connection goes down with a blocking
39
- # consumer running (it uses callbacks, as the RabbitMQ Java client does).
40
- #
41
- # However, MarchHare::Channel will make sure to unblock all blocking consumers
42
- # on any internal shutdown, so #consume will return and another loop iteration
43
- # will run.
44
- #
45
- # This is very similar to how the Bunny implementation works and is sufficient
46
- # for our needs: it recovers successfully after RabbitMQ is kill -9ed, the
47
- # network device is shut down, etc. MK.
48
- until @break_out_of_the_loop.get do
49
- begin
50
- setup
51
- consume
52
- rescue MarchHare::Exception, java.lang.Throwable, com.rabbitmq.client.AlreadyClosedException => e
53
- n = 10
54
- @logger.error("RabbitMQ connection error: #{e}. Will reconnect in #{n} seconds...")
55
-
56
- sleep n
57
- retry
58
- rescue LogStash::ShutdownSignal => ss
59
- shutdown_consumer
60
- end
61
-
62
- n = 10
63
- @logger.error("RabbitMQ connection error: #{e}. Will reconnect in #{n} seconds...")
64
- end
65
- end
66
-
67
- def teardown
68
- shutdown_consumer
69
-
70
- @ch.close if @ch && @ch.open?
71
- @connection.close if @connection && @connection.open?
72
-
73
- finished
74
- end
75
-
76
- #
77
- # Implementation
78
- #
79
-
80
- protected
81
-
82
- def setup
83
- return if terminating?
84
-
85
- @conn = MarchHare.connect(@settings)
86
- @logger.info("Connected to RabbitMQ #{@connection_url}")
87
-
88
- @ch = @conn.create_channel.tap do |ch|
89
- ch.prefetch = @prefetch_count
90
- end
91
-
92
- @arguments_hash = Hash[*@arguments]
93
-
94
- @q = @ch.queue(@queue,
95
- :durable => @durable,
96
- :auto_delete => @auto_delete,
97
- :exclusive => @exclusive,
98
- :passive => @passive,
99
- :arguments => @arguments)
100
-
101
- # exchange binding is optional for the input
102
- if @exchange
103
- @q.bind(@exchange, :routing_key => @key)
104
- end
105
- end
106
-
107
- def consume
108
- return if terminating?
109
-
110
- # we manually build a consumer here to be able to keep a reference to it
111
- # in an @ivar even though we use a blocking version of HB::Queue#subscribe
112
- @consumer = @q.build_consumer(:block => true) do |metadata, data|
113
- @codec.decode(data) do |event|
114
- decorate(event)
115
- @output_queue << event if event
116
- end
117
- @ch.ack(metadata.delivery_tag) if @ack
118
- end
119
- @q.subscribe_with(@consumer, :manual_ack => @ack, :block => true)
120
- end
121
-
122
- def shutdown_consumer
123
- @break_out_of_the_loop.set(true)
124
-
125
- @consumer.cancel
126
- @consumer.gracefully_shut_down
127
- end
128
- end # MarchHareImpl
129
- end
data/rakelib/publish.rake DELETED
@@ -1,9 +0,0 @@
1
- require "gem_publisher"
2
-
3
- desc "Publish gem to RubyGems.org"
4
- task :publish_gem do |t|
5
- gem_file = Dir.glob(File.expand_path('../*.gemspec',File.dirname(__FILE__))).first
6
- gem = GemPublisher.publish_if_updated(gem_file, :rubygems)
7
- puts "Published #{gem}" if gem
8
- end
9
-
data/rakelib/vendor.rake DELETED
@@ -1,169 +0,0 @@
1
- require "net/http"
2
- require "uri"
3
- require "digest/sha1"
4
-
5
- def vendor(*args)
6
- return File.join("vendor", *args)
7
- end
8
-
9
- directory "vendor/" => ["vendor"] do |task, args|
10
- mkdir task.name
11
- end
12
-
13
- def fetch(url, sha1, output)
14
-
15
- puts "Downloading #{url}"
16
- actual_sha1 = download(url, output)
17
-
18
- if actual_sha1 != sha1
19
- fail "SHA1 does not match (expected '#{sha1}' but got '#{actual_sha1}')"
20
- end
21
- end # def fetch
22
-
23
- def file_fetch(url, sha1)
24
- filename = File.basename( URI(url).path )
25
- output = "vendor/#{filename}"
26
- task output => [ "vendor/" ] do
27
- begin
28
- actual_sha1 = file_sha1(output)
29
- if actual_sha1 != sha1
30
- fetch(url, sha1, output)
31
- end
32
- rescue Errno::ENOENT
33
- fetch(url, sha1, output)
34
- end
35
- end.invoke
36
-
37
- return output
38
- end
39
-
40
- def file_sha1(path)
41
- digest = Digest::SHA1.new
42
- fd = File.new(path, "r")
43
- while true
44
- begin
45
- digest << fd.sysread(16384)
46
- rescue EOFError
47
- break
48
- end
49
- end
50
- return digest.hexdigest
51
- ensure
52
- fd.close if fd
53
- end
54
-
55
- def download(url, output)
56
- uri = URI(url)
57
- digest = Digest::SHA1.new
58
- tmp = "#{output}.tmp"
59
- Net::HTTP.start(uri.host, uri.port, :use_ssl => (uri.scheme == "https")) do |http|
60
- request = Net::HTTP::Get.new(uri.path)
61
- http.request(request) do |response|
62
- fail "HTTP fetch failed for #{url}. #{response}" if [200, 301].include?(response.code)
63
- size = (response["content-length"].to_i || -1).to_f
64
- count = 0
65
- File.open(tmp, "w") do |fd|
66
- response.read_body do |chunk|
67
- fd.write(chunk)
68
- digest << chunk
69
- if size > 0 && $stdout.tty?
70
- count += chunk.bytesize
71
- $stdout.write(sprintf("\r%0.2f%%", count/size * 100))
72
- end
73
- end
74
- end
75
- $stdout.write("\r \r") if $stdout.tty?
76
- end
77
- end
78
-
79
- File.rename(tmp, output)
80
-
81
- return digest.hexdigest
82
- rescue SocketError => e
83
- puts "Failure while downloading #{url}: #{e}"
84
- raise
85
- ensure
86
- File.unlink(tmp) if File.exist?(tmp)
87
- end # def download
88
-
89
- def untar(tarball, &block)
90
- require "archive/tar/minitar"
91
- tgz = Zlib::GzipReader.new(File.open(tarball))
92
- # Pull out typesdb
93
- tar = Archive::Tar::Minitar::Input.open(tgz)
94
- tar.each do |entry|
95
- path = block.call(entry)
96
- next if path.nil?
97
- parent = File.dirname(path)
98
-
99
- mkdir_p parent unless File.directory?(parent)
100
-
101
- # Skip this file if the output file is the same size
102
- if entry.directory?
103
- mkdir path unless File.directory?(path)
104
- else
105
- entry_mode = entry.instance_eval { @mode } & 0777
106
- if File.exists?(path)
107
- stat = File.stat(path)
108
- # TODO(sissel): Submit a patch to archive-tar-minitar upstream to
109
- # expose headers in the entry.
110
- entry_size = entry.instance_eval { @size }
111
- # If file sizes are same, skip writing.
112
- next if stat.size == entry_size && (stat.mode & 0777) == entry_mode
113
- end
114
- puts "Extracting #{entry.full_name} from #{tarball} #{entry_mode.to_s(8)}"
115
- File.open(path, "w") do |fd|
116
- # eof? check lets us skip empty files. Necessary because the API provided by
117
- # Archive::Tar::Minitar::Reader::EntryStream only mostly acts like an
118
- # IO object. Something about empty files in this EntryStream causes
119
- # IO.copy_stream to throw "can't convert nil into String" on JRuby
120
- # TODO(sissel): File a bug about this.
121
- while !entry.eof?
122
- chunk = entry.read(16384)
123
- fd.write(chunk)
124
- end
125
- #IO.copy_stream(entry, fd)
126
- end
127
- File.chmod(entry_mode, path)
128
- end
129
- end
130
- tar.close
131
- File.unlink(tarball) if File.file?(tarball)
132
- end # def untar
133
-
134
- def ungz(file)
135
-
136
- outpath = file.gsub('.gz', '')
137
- tgz = Zlib::GzipReader.new(File.open(file))
138
- begin
139
- File.open(outpath, "w") do |out|
140
- IO::copy_stream(tgz, out)
141
- end
142
- File.unlink(file)
143
- rescue
144
- File.unlink(outpath) if File.file?(outpath)
145
- raise
146
- end
147
- tgz.close
148
- end
149
-
150
- desc "Process any vendor files required for this plugin"
151
- task "vendor" do |task, args|
152
-
153
- @files.each do |file|
154
- download = file_fetch(file['url'], file['sha1'])
155
- if download =~ /.tar.gz/
156
- prefix = download.gsub('.tar.gz', '').gsub('vendor/', '')
157
- untar(download) do |entry|
158
- if !file['files'].nil?
159
- next unless file['files'].include?(entry.full_name.gsub(prefix, ''))
160
- out = entry.full_name.split("/").last
161
- end
162
- File.join('vendor', out)
163
- end
164
- elsif download =~ /.gz/
165
- ungz(download)
166
- end
167
- end
168
-
169
- end