pipeline_toolkit 1.0.4 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.markdown +20 -0
- data/README.markdown +98 -0
- data/bin/msg_generator +13 -0
- data/bin/msg_probe +13 -0
- data/bin/msg_push +13 -0
- data/bin/msg_sink +14 -0
- data/bin/msg_subscribe +13 -0
- data/lib/pipeline_toolkit.rb +17 -0
- data/lib/pipeline_toolkit/amqp/abstract.rb +95 -0
- data/lib/pipeline_toolkit/amqp/reader.rb +64 -0
- data/lib/pipeline_toolkit/amqp/writer.rb +54 -0
- data/lib/pipeline_toolkit/commands/msg_generator/cli.rb +45 -0
- data/lib/pipeline_toolkit/commands/msg_probe/cli.rb +46 -0
- data/lib/pipeline_toolkit/commands/msg_push/cli.rb +58 -0
- data/lib/pipeline_toolkit/commands/msg_sink/cli.rb +41 -0
- data/lib/pipeline_toolkit/commands/msg_subscribe/cli.rb +58 -0
- data/lib/pipeline_toolkit/default_logger.rb +126 -11
- data/lib/pipeline_toolkit/handlers/message_handler.rb +38 -0
- data/lib/pipeline_toolkit/message_coder.rb +18 -8
- data/lib/pipeline_toolkit/message_command.rb +138 -61
- data/lib/pipeline_toolkit/message_generator.rb +21 -0
- data/lib/pipeline_toolkit/message_probe.rb +6 -6
- data/lib/pipeline_toolkit/message_pusher.rb +51 -54
- data/lib/pipeline_toolkit/message_sink.rb +1 -1
- data/lib/pipeline_toolkit/message_subscriber.rb +182 -201
- data/lib/pipeline_toolkit/monitoring/monitor_server.rb +124 -0
- data/spec/eventmachine_helper.rb +44 -0
- data/spec/message_subscriber_spec.rb +64 -0
- data/spec/spec_helper.rb +15 -0
- metadata +202 -47
- data/.gitignore +0 -5
- data/README.rdoc +0 -70
- data/Rakefile +0 -40
- data/VERSION +0 -1
- data/bin/msg_generator.rb +0 -0
- data/bin/msg_probe.rb +0 -15
- data/bin/msg_push.rb +0 -25
- data/bin/msg_sink.rb +0 -11
- data/bin/msg_subscribe.rb +0 -27
- data/monitor/munin.rb +0 -91
- data/pipeline_toolkit.gemspec +0 -72
data/README.rdoc
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
= Pipeline Toolkit
|
2
|
-
by VisFleet
|
3
|
-
|
4
|
-
Command line tools for processing messages by constructing a pipeline of workers. AMQP and Unix pipes are used to construct the pipeline. Messages are simple Hashes (serialized as YAML) so they can hold any values and change throughout the processing.
|
5
|
-
|
6
|
-
Provides:
|
7
|
-
- Processing acknowledgments, ensuring the a message is only disposed of once it has been successful processed
|
8
|
-
- Performance. Messages are moved through the pipeline fast
|
9
|
-
- Command line tools for:
|
10
|
-
- Subscribing to messages from an AMQP queue
|
11
|
-
- Pushing messages back onto an AMQP exchange
|
12
|
-
- Monitoring performance (see msg_probe)
|
13
|
-
- A base module (MessageCommand) to include into your own classes to quickly make workers.
|
14
|
-
|
15
|
-
== Install
|
16
|
-
|
17
|
-
> sudo gem install pipeline_toolkit
|
18
|
-
|
19
|
-
=== Dependancies
|
20
|
-
|
21
|
-
It is assumed that you have:
|
22
|
-
- An AMQP msg server to pop and push messages to (e.g. http://www.rabbitmq.com/)
|
23
|
-
- A *nix system, such as Linux or Mac OS X.
|
24
|
-
|
25
|
-
== Usage
|
26
|
-
|
27
|
-
1. Create your worker
|
28
|
-
|
29
|
-
class MyWorker
|
30
|
-
include MessageCommand
|
31
|
-
|
32
|
-
def process_message(msg)
|
33
|
-
# do stuff here
|
34
|
-
msg
|
35
|
-
end
|
36
|
-
end
|
37
|
-
MyWorker.new.start
|
38
|
-
|
39
|
-
2. Hook it up to a AMQP message source
|
40
|
-
|
41
|
-
> msg_subscribe.rb -q source | my_worker.rb | msg_push.rb -x dest
|
42
|
-
|
43
|
-
You can learn more about the command line tools and what options are available by using their help command.
|
44
|
-
|
45
|
-
> msg_subscriber --help
|
46
|
-
> msg_push --help
|
47
|
-
> msg_sink --help
|
48
|
-
> msg_probe --help
|
49
|
-
|
50
|
-
== Examples
|
51
|
-
|
52
|
-
Generate a bunch of sample messages and push them to an AMQP exchange 'test-exchange'. Hook up a pipe to consume and push results to /dev/null. Goto http://localhost:9090 to see message throughput.
|
53
|
-
|
54
|
-
> msg_generator.rb | msg_push.rb -x test-exchange
|
55
|
-
> msg_subscribe.rb --http-port 9090 -x test-exchange -q test_queue > /dev/null
|
56
|
-
|
57
|
-
Same as above, but this time with acknowledgements switched on. This guarantees that a message isn't removed from the message server until handled. msg_sink.rb acknowledges all messages.
|
58
|
-
|
59
|
-
> msg_generator.rb | msg_push.rb -x test-exchange
|
60
|
-
> msg_subscribe.rb -a -x test-exchange -q test_queue | msg_sink.rb
|
61
|
-
|
62
|
-
== Todo
|
63
|
-
|
64
|
-
- Logging. For the moment we're using SysLogLogger (which requires Syslog). This needs to be switched to the default ruby logging, and we need to find out a way to plug in alternatives if required.
|
65
|
-
|
66
|
-
- DNS-SD is broken. See http://github.com/tenderlove/dnssd/issues#issue/3
|
67
|
-
|
68
|
-
- Decide if we want to support other exchange, queue and binding configurations. For example, exchanges are always fanout and durable at the moment.
|
69
|
-
|
70
|
-
|
data/Rakefile
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "pipeline_toolkit"
|
8
|
-
gem.summary = %Q{Toolkit for building processing pipelines using Unix Pipes and AMQP messages}
|
9
|
-
gem.email = "labs@visfleet.com"
|
10
|
-
gem.homepage = "http://github.com/visfleet/pipeline_toolkit"
|
11
|
-
gem.authors = ["Aisha Fenton"]
|
12
|
-
gem.executables = ["msg_probe.rb", "msg_subscribe.rb", "msg_push.rb", "msg_sink.rb", "msg_generator.rb"]
|
13
|
-
gem.add_runtime_dependency('amqp', ">=0.6.5")
|
14
|
-
gem.add_runtime_dependency('trollop', ">=1.14")
|
15
|
-
gem.add_runtime_dependency('eventmachine', ">=0.12.10")
|
16
|
-
gem.add_runtime_dependency('eventmachine_httpserver', ">=0.2.0")
|
17
|
-
gem.add_runtime_dependency('SyslogLogger', ">=1.4.0")
|
18
|
-
end
|
19
|
-
Jeweler::GemcutterTasks.new
|
20
|
-
|
21
|
-
rescue LoadError
|
22
|
-
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
23
|
-
end
|
24
|
-
|
25
|
-
task :default => :build
|
26
|
-
|
27
|
-
require 'rake/rdoctask'
|
28
|
-
Rake::RDocTask.new do |rdoc|
|
29
|
-
if File.exist?('VERSION.yml')
|
30
|
-
config = YAML.load(File.read('VERSION.yml'))
|
31
|
-
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
32
|
-
else
|
33
|
-
version = ""
|
34
|
-
end
|
35
|
-
|
36
|
-
rdoc.rdoc_dir = 'rdoc'
|
37
|
-
rdoc.title = "pipeline_toolkit #{version}"
|
38
|
-
rdoc.rdoc_files.include('README*')
|
39
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
40
|
-
end
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
1.0.4
|
data/bin/msg_generator.rb
DELETED
File without changes
|
data/bin/msg_probe.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'trollop'
|
5
|
-
require 'pipeline_toolkit'
|
6
|
-
|
7
|
-
opts = Trollop::options do
|
8
|
-
opt :interval, "Time in seconds between updates", :short => "i", :default => 2
|
9
|
-
opt :http_port, "The port the HTTP server runs on. Default is a random port between 10000-11000", :type => :integer
|
10
|
-
opt :name, "The name of the probe. Used in monitoring", :type => :string, :short => 'n'
|
11
|
-
opt :dnssd, "Switches on DNSSD (i.e. Bonjour) for the monitoring interface", :short => 'd'
|
12
|
-
end
|
13
|
-
|
14
|
-
MessageProbe.new(opts).start
|
15
|
-
|
data/bin/msg_push.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'trollop'
|
5
|
-
require 'pipeline_toolkit'
|
6
|
-
|
7
|
-
opts = Trollop::options do
|
8
|
-
opt :exchanges, "The destination exchange(s)", :short => "x", :type => :strings
|
9
|
-
opt :key_eval, "A string of ruby code that is evaluated to produce a routing key for a given message.
|
10
|
-
By default each message has no routing key", :short => "e", :type => :string
|
11
|
-
opt :key_file, "A ruby file that gets included which contains a custom route_key method", :short => "f", :type => :string
|
12
|
-
|
13
|
-
# Msg server
|
14
|
-
opt :host, "The AMQP message server host", :default => "localhost"
|
15
|
-
opt :port, "The AMQP message server port", :default => "5672"
|
16
|
-
opt :user, "The AMQP message server username", :default => "guest"
|
17
|
-
opt :pass, "The AMQP message server username", :default => "guest"
|
18
|
-
opt :vhost, "The AMQP message server vhost", :default => "/"
|
19
|
-
end
|
20
|
-
|
21
|
-
mp = MessagePusher.new(opts)
|
22
|
-
# FIXME. Should be in MessageCommand class
|
23
|
-
Signal.trap('INT') { mp.stop }
|
24
|
-
Signal.trap('TERM'){ mp.stop }
|
25
|
-
mp.start
|
data/bin/msg_sink.rb
DELETED
data/bin/msg_subscribe.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'trollop'
|
4
|
-
require 'pipeline_toolkit'
|
5
|
-
|
6
|
-
opts = Trollop::options do
|
7
|
-
# Monitoring
|
8
|
-
opt :name, "The name used to describe the entire process chain", :short => "n", :type => :string
|
9
|
-
opt :http_port, "The port the HTTP monitoring server runs on. Default is a random port between 10000-11000", :type => :integer
|
10
|
-
opt :dnssd, "Switches on DNSSD (i.e. Bonjour) for the monitoring interface", :short => 'd'
|
11
|
-
|
12
|
-
# Messages
|
13
|
-
opt :queue, "The source queue", :short => "q", :type => :string, :required => true
|
14
|
-
opt :ack, "Switch that requires that messages are successfully processed before continuing with the next message", :short => "a"
|
15
|
-
opt :topic, "The queue topic to subscribe to", :short => "t", :type => :string
|
16
|
-
opt :max_unackd, "The maximum number of unaknowledged messages to buffer before waiting for them to be acknowledged. Defaults to 100", :default => 100
|
17
|
-
opt :exchange_bind, "Binds the the queue to the specified exchange. The created exchange is (for now) fanout, durable, and not passive", :short => "x", :type => :string
|
18
|
-
|
19
|
-
# Msg server
|
20
|
-
opt :host, "The AMQP message server host", :default => "localhost"
|
21
|
-
opt :port, "The AMQP message server port", :default => "5672"
|
22
|
-
opt :user, "The AMQP message server username", :default => "guest"
|
23
|
-
opt :pass, "The AMQP message server username", :default => "guest", :short => "w"
|
24
|
-
opt :vhost, "The AMQP message server vhost", :default => "/"
|
25
|
-
end
|
26
|
-
|
27
|
-
ms = MessageSubscriber.new(opts).start
|
data/monitor/munin.rb
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'open-uri'
|
4
|
-
require 'trollop'
|
5
|
-
require 'nokogiri'
|
6
|
-
|
7
|
-
class MuninPlugin
|
8
|
-
|
9
|
-
def initialize(is_config, opts)
|
10
|
-
@probe_urls = opts.probe_urls
|
11
|
-
|
12
|
-
self.get_probes
|
13
|
-
|
14
|
-
if is_config
|
15
|
-
self.config
|
16
|
-
else
|
17
|
-
self.data
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def get_probes
|
22
|
-
@probes = []
|
23
|
-
@probe_urls.each_with_index do |url, idx|
|
24
|
-
@probes << get_probe(url)
|
25
|
-
end
|
26
|
-
@probes
|
27
|
-
end
|
28
|
-
|
29
|
-
def get_probe(url)
|
30
|
-
probe = Probe.new
|
31
|
-
doc = Nokogiri::HTML(open(url))
|
32
|
-
probe.name = extract_mf_value(doc, "name")
|
33
|
-
probe.mps = extract_mf_value(doc, "mps")
|
34
|
-
probe.uptime = extract_mf_value(doc, "uptime")
|
35
|
-
probe
|
36
|
-
end
|
37
|
-
|
38
|
-
# Extracts the microformat value from the HTML doc
|
39
|
-
def extract_mf_value(doc, key)
|
40
|
-
doc.css(".#{key}").first.content
|
41
|
-
end
|
42
|
-
|
43
|
-
def config
|
44
|
-
config=<<-EOL
|
45
|
-
graph_title Message Probe Throughput
|
46
|
-
graph_vlabel messages per second
|
47
|
-
graph_category Message Probe
|
48
|
-
EOL
|
49
|
-
|
50
|
-
@probes.each do |probe|
|
51
|
-
config << "probe_#{probe.name}.label #{probe.name}\n"
|
52
|
-
end
|
53
|
-
|
54
|
-
puts config
|
55
|
-
end
|
56
|
-
|
57
|
-
def data
|
58
|
-
data = ""
|
59
|
-
@probes.each do |probe|
|
60
|
-
data << "#{probe.name}.value #{probe.mps}\n"
|
61
|
-
end
|
62
|
-
|
63
|
-
puts data
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
class Probe
|
69
|
-
attr_accessor :name, :mps, :uptime
|
70
|
-
end
|
71
|
-
|
72
|
-
SUB_COMMANDS = %w{run config}
|
73
|
-
|
74
|
-
global_opts = Trollop::options do
|
75
|
-
banner <<-EOS
|
76
|
-
Munin plugin
|
77
|
-
Usage:
|
78
|
-
munin.rb [run|config] [options]
|
79
|
-
|
80
|
-
For more help run
|
81
|
-
munin.rb [command] --help
|
82
|
-
EOS
|
83
|
-
stop_on SUB_COMMANDS
|
84
|
-
end
|
85
|
-
|
86
|
-
is_config = (ARGV.shift == "config")
|
87
|
-
opts = Trollop::options do
|
88
|
-
opt :probe_urls, "The probe's URL", :short => "p", :type => :strings, :default => ["http://127.0.0.1:9070"]
|
89
|
-
end
|
90
|
-
|
91
|
-
MuninPlugin.new(is_config, opts)
|
data/pipeline_toolkit.gemspec
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = %q{pipeline_toolkit}
|
8
|
-
s.version = "1.0.4"
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Aisha Fenton"]
|
12
|
-
s.date = %q{2010-01-15}
|
13
|
-
s.email = %q{labs@visfleet.com}
|
14
|
-
s.executables = ["msg_probe.rb", "msg_subscribe.rb", "msg_push.rb", "msg_sink.rb", "msg_generator.rb"]
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"README.rdoc"
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
".gitignore",
|
20
|
-
"README.rdoc",
|
21
|
-
"Rakefile",
|
22
|
-
"VERSION",
|
23
|
-
"bin/msg_generator.rb",
|
24
|
-
"bin/msg_probe.rb",
|
25
|
-
"bin/msg_push.rb",
|
26
|
-
"bin/msg_sink.rb",
|
27
|
-
"bin/msg_subscribe.rb",
|
28
|
-
"lib/pipeline_toolkit.rb",
|
29
|
-
"lib/pipeline_toolkit/default_logger.rb",
|
30
|
-
"lib/pipeline_toolkit/message_coder.rb",
|
31
|
-
"lib/pipeline_toolkit/message_command.rb",
|
32
|
-
"lib/pipeline_toolkit/message_probe.rb",
|
33
|
-
"lib/pipeline_toolkit/message_pusher.rb",
|
34
|
-
"lib/pipeline_toolkit/message_sink.rb",
|
35
|
-
"lib/pipeline_toolkit/message_subscriber.rb",
|
36
|
-
"lib/pipeline_toolkit/open_hash.rb",
|
37
|
-
"lib/pipeline_toolkit/socket_util.rb",
|
38
|
-
"monitor/munin.rb",
|
39
|
-
"pipeline_toolkit.gemspec"
|
40
|
-
]
|
41
|
-
s.homepage = %q{http://github.com/visfleet/pipeline_toolkit}
|
42
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
43
|
-
s.require_paths = ["lib"]
|
44
|
-
s.rubygems_version = %q{1.3.5}
|
45
|
-
s.summary = %q{Toolkit for building processing pipelines using Unix Pipes and AMQP messages}
|
46
|
-
|
47
|
-
if s.respond_to? :specification_version then
|
48
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
49
|
-
s.specification_version = 3
|
50
|
-
|
51
|
-
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
52
|
-
s.add_runtime_dependency(%q<amqp>, [">= 0.6.5"])
|
53
|
-
s.add_runtime_dependency(%q<trollop>, [">= 1.14"])
|
54
|
-
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.10"])
|
55
|
-
s.add_runtime_dependency(%q<eventmachine_httpserver>, [">= 0.2.0"])
|
56
|
-
s.add_runtime_dependency(%q<SyslogLogger>, [">= 1.4.0"])
|
57
|
-
else
|
58
|
-
s.add_dependency(%q<amqp>, [">= 0.6.5"])
|
59
|
-
s.add_dependency(%q<trollop>, [">= 1.14"])
|
60
|
-
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
61
|
-
s.add_dependency(%q<eventmachine_httpserver>, [">= 0.2.0"])
|
62
|
-
s.add_dependency(%q<SyslogLogger>, [">= 1.4.0"])
|
63
|
-
end
|
64
|
-
else
|
65
|
-
s.add_dependency(%q<amqp>, [">= 0.6.5"])
|
66
|
-
s.add_dependency(%q<trollop>, [">= 1.14"])
|
67
|
-
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
68
|
-
s.add_dependency(%q<eventmachine_httpserver>, [">= 0.2.0"])
|
69
|
-
s.add_dependency(%q<SyslogLogger>, [">= 1.4.0"])
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|