recognizer 0.0.10 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.org CHANGED
@@ -1,28 +1,40 @@
1
1
  * Welcome to Recognizer
2
- A Graphite Carbon AMQP impostor, sending metrics to [[https://metrics.librato.com/][Librato Metrics]].
2
+ A Graphite Carbon impostor, sending metrics to [[https://metrics.librato.com/][Librato Metrics]].
3
+
4
+ TCP plain text & AMQP support.
3
5
 
4
6
  [[https://github.com/portertech/recognizer/raw/master/recognizer.gif]]
5
7
  * Install
8
+ Executable Java JAR
9
+ : wget https://github.com/downloads/portertech/recognizer/recognizer.jar
10
+ RubyGems
6
11
  : gem install recognizer
7
12
  * Configure
8
13
  Example: =config.json=
9
14
  : {
10
15
  : "librato": {
11
16
  : "email": "email@example.com",
12
- : "api_key": "706325cf16d84d098127e143221dd180706325cf16d84d098127e143221dd180",
13
- : "flush_interval": 5
17
+ : "api_key": "706325cf16d84d098127e143221dd180706325cf16d84d098127e143221dd180"
14
18
  : },
15
19
  : "amqp": {
16
- : "host": "hostname",
17
- : "user": "username",
18
- : "pass": "password"
20
+ : "host": "localhost"
21
+ : },
22
+ : "tcp": {
23
+ : "port": 2003
19
24
  : }
20
25
  : }
21
26
  * Usage
27
+ Executable Java JAR
28
+ : java -jar recognizer.jar -h
29
+ RubyGems
30
+ : recognizer -h
31
+
22
32
  : Usage: recognizer (options)
23
33
  : -c, --config CONFIG The config file path
24
34
  : -h, --help Show this message
25
35
  * More
36
+ By default, Recognizer uses the source: =recognizer=
37
+
26
38
  Example metric path: =production.i-424242.cpu.user=
27
39
 
28
40
  Extract the metric source from the metric path using a regular expression
@@ -37,6 +49,16 @@
37
49
  : {
38
50
  : "librato": {
39
51
  : "metric_source": "example"
40
- By default, Recognizer uses the source: =recognizer=
52
+
53
+ By default, Recognizer uses =20= threads for the TCP server
54
+
55
+ Specify the number of TCP server threads
56
+ : {
57
+ : "tcp": {
58
+ : "threads": 30
59
+
60
+ By default, Recognizer uses an AMQP queue named: =recognizer=
61
+
62
+ By default, Recognizer binds its AMQP queue to the exchange: =graphite=
41
63
  * License
42
64
  Recognizer is released under the [[https://github.com/portertech/recognizer/raw/master/MIT-LICENSE.txt][MIT license]].
@@ -4,46 +4,48 @@ require "bunny"
4
4
 
5
5
  module Recognizer
6
6
  class AMQP
7
- def initialize(thread_queue, options)
8
- unless thread_queue && options.is_a?(Hash)
7
+ def initialize(carbon_queue, logger, options)
8
+ unless carbon_queue && options.is_a?(Hash)
9
9
  raise "You must provide a thread queue and options"
10
10
  end
11
11
 
12
- options[:amqp] ||= Hash.new
13
- options[:amqp][:exchange] ||= Hash.new
12
+ if options.has_key?(:amqp)
13
+ options[:amqp][:exchange] ||= Hash.new
14
14
 
15
- exchange_name = options[:amqp][:exchange][:name] || "graphite"
16
- durable = options[:amqp][:exchange][:durable] || false
17
- routing_key = options[:amqp][:exchange][:routing_key] || "#"
18
- exchange_type = options[:amqp][:exchange][:type] || :topic
15
+ exchange_name = options[:amqp][:exchange][:name] || "graphite"
16
+ durable = options[:amqp][:exchange][:durable] || false
17
+ routing_key = options[:amqp][:exchange][:routing_key] || "#"
18
+ exchange_type = options[:amqp][:exchange][:type] || :topic
19
19
 
20
- amqp = Bunny.new(options[:amqp].reject { |key, value| key == :exchange })
21
- amqp.start
20
+ amqp = Bunny.new(options[:amqp].reject { |key, value| key == :exchange })
21
+ amqp.start
22
22
 
23
- exchange = amqp.exchange(exchange_name, :type => exchange_type.to_sym, :durable => durable)
24
- queue = amqp.queue("recognizer")
25
- queue.bind(exchange, :key => routing_key)
23
+ exchange = amqp.exchange(exchange_name, :type => exchange_type.to_sym, :durable => durable)
24
+ queue = amqp.queue("recognizer")
25
+ queue.bind(exchange, :key => routing_key)
26
26
 
27
- Thread.abort_on_exception = true
27
+ Thread.abort_on_exception = true
28
28
 
29
- consumer = Thread.new do
30
- puts "Awaiting the metrics with impatience ..."
31
- queue.subscribe do |message|
32
- payload = message[:payload]
33
- msg_routing_key = message[:routing_key] || message[:delivery_details][:routing_key]
34
- lines = payload.split("\n")
35
- lines.each do |line|
36
- line = line.strip
37
- case line.split("\s").count
38
- when 3
39
- thread_queue.push(line)
40
- when 2
41
- thread_queue.push("#{msg_routing_key} #{line}")
29
+ Thread.new do
30
+ logger.info("AMQP -- Awaiting metrics with impatience ...")
31
+ queue.subscribe do |message|
32
+ payload = message[:payload]
33
+ msg_routing_key = message[:routing_key] || message[:delivery_details][:routing_key]
34
+ lines = payload.split("\n")
35
+ lines.each do |line|
36
+ line = line.strip
37
+ case line.split("\s").count
38
+ when 3
39
+ carbon_queue.push(line)
40
+ when 2
41
+ carbon_queue.push("#{msg_routing_key} #{line}")
42
+ end
42
43
  end
43
44
  end
44
45
  end
46
+ else
47
+ logger.warn("AMQP -- Not configured")
45
48
  end
46
- consumer.join
47
49
  end
48
50
  end
49
51
  end
@@ -7,8 +7,8 @@ require File.join(File.dirname(__FILE__), 'patches', 'float')
7
7
 
8
8
  module Recognizer
9
9
  class Librato
10
- def initialize(thread_queue, options)
11
- unless thread_queue && options.is_a?(Hash)
10
+ def initialize(carbon_queue, logger, options)
11
+ unless carbon_queue && options.is_a?(Hash)
12
12
  raise "You must provide a thread queue and options"
13
13
  end
14
14
  unless options[:librato][:email] && options[:librato][:api_key]
@@ -26,11 +26,11 @@ module Recognizer
26
26
  loop do
27
27
  sleep(options[:librato][:flush_interval] || 10)
28
28
  unless librato.empty?
29
- puts "Attempting to flush metrics to Librato"
29
+ logger.info("Attempting to flush metrics to Librato")
30
30
  mutex.synchronize do
31
31
  librato.submit
32
32
  end
33
- puts "Successfully flushed metrics to Librato"
33
+ logger.info("Successfully flushed metrics to Librato")
34
34
  end
35
35
  end
36
36
  end
@@ -51,7 +51,7 @@ module Recognizer
51
51
 
52
52
  Thread.new do
53
53
  loop do
54
- graphite_formated = thread_queue.pop
54
+ graphite_formated = carbon_queue.pop
55
55
  begin
56
56
  path, value, timestamp = graphite_formated.split(" ").inject([]) do |result, part|
57
57
  result << (result.empty? ? part.split(".") : Float(part).pretty)
@@ -61,11 +61,11 @@ module Recognizer
61
61
  path.delete(source)
62
62
  metric = {path.join(".") => {:value => value, :measure_time => timestamp, :source => source}}
63
63
  mutex.synchronize do
64
- puts "Adding metric to queue: #{metric.inspect}"
64
+ logger.info("Adding metric to queue: #{metric.inspect}")
65
65
  librato.add(metric)
66
66
  end
67
67
  rescue ArgumentError
68
- puts "Invalid metric: #{graphite_formated}"
68
+ logger.info("Invalid metric: #{graphite_formated}")
69
69
  end
70
70
  end
71
71
  end
@@ -0,0 +1,53 @@
1
+ require "rubygems"
2
+ require "timeout"
3
+ require "thread"
4
+ require "socket"
5
+
6
+ module Recognizer
7
+ class TCP
8
+ def initialize(carbon_queue, logger, options)
9
+ unless carbon_queue && options.is_a?(Hash)
10
+ raise "You must provide a thread queue and options"
11
+ end
12
+
13
+ options[:tcp] ||= Hash.new
14
+
15
+ threads = options[:tcp][:threads] || 20
16
+ port = options[:tcp][:port] || 2003
17
+
18
+ tcp_server = TCPServer.new("0.0.0.0", port)
19
+ tcp_connections = Queue.new
20
+
21
+ Thread.abort_on_exception = true
22
+
23
+ threads.times do
24
+ Thread.new do
25
+ loop do
26
+ if connection = tcp_connections.shift
27
+ begin
28
+ lines = timeout(12) do
29
+ connection.gets.split("\n")
30
+ end
31
+ lines.each do |line|
32
+ line = line.strip
33
+ if line.split("\s").count == 3
34
+ carbon_queue.push(line)
35
+ end
36
+ end
37
+ rescue Timeout::Error
38
+ connection.close
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ Thread.new do
46
+ logger.info("TCP -- Awaiting metrics with impatience ...")
47
+ loop do
48
+ tcp_connections.push(tcp_server.accept)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,3 @@
1
1
  module Recognizer
2
- VERSION = "0.0.10"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/recognizer.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "recognizer/cli"
2
2
  require "recognizer/config"
3
3
  require "recognizer/librato"
4
+ require "recognizer/tcp"
4
5
  require "recognizer/amqp"
5
6
 
6
7
  module Recognizer
@@ -9,8 +10,13 @@ module Recognizer
9
10
  cli_options = cli.read
10
11
  config = Recognizer::Config.new(cli_options)
11
12
  config_options = config.read
12
- thread_queue = Queue.new
13
- Recognizer::Librato.new(thread_queue, config_options)
14
- Recognizer::AMQP.new(thread_queue, config_options)
13
+ carbon_queue = Queue.new
14
+ logger = Logger.new(STDOUT)
15
+ Recognizer::Librato.new(carbon_queue, logger, config_options)
16
+ Recognizer::TCP.new(carbon_queue, logger, config_options)
17
+ Recognizer::AMQP.new(carbon_queue, logger, config_options)
18
+ loop do
19
+ sleep 30
20
+ end
15
21
  end
16
22
  end
data/recognizer.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["Sean Porter"]
9
9
  s.email = ["portertech@gmail.com"]
10
10
  s.homepage = "https://github.com/portertech/recognizer"
11
- s.summary = "A Graphite Carbon AMQP impostor, sending metrics to Librato Metrics."
12
- s.description = "A Graphite Carbon AMQP impostor, sending metrics to Librato Metrics."
11
+ s.summary = "A Graphite Carbon impostor, sending metrics to Librato Metrics."
12
+ s.description = "A drop-in replacement for Graphite Carbon (TCP & AMQP), sending metrics to Librato Metrics."
13
13
 
14
14
  s.rubyforge_project = "recognizer"
15
15
 
@@ -17,8 +17,8 @@ Gem::Specification.new do |s|
17
17
  s.executables = Dir.glob("bin/**/*").map { |file| File.basename(file) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_dependency("librato-metrics", "0.4.0")
21
- s.add_dependency("bunny", "0.7.9")
22
- s.add_dependency("mixlib-cli", ">= 1.1.0")
23
20
  s.add_dependency("json")
21
+ s.add_dependency("mixlib-cli", ">= 1.1.0")
22
+ s.add_dependency("bunny", "0.7.9")
23
+ s.add_dependency("librato-metrics", "0.4.2")
24
24
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recognizer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 10
10
- version: 0.0.10
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sean Porter
@@ -15,72 +15,72 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-06 00:00:00 -08:00
18
+ date: 2012-03-10 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: librato-metrics
22
+ name: json
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - "="
27
+ - - ">="
28
28
  - !ruby/object:Gem::Version
29
- hash: 15
29
+ hash: 3
30
30
  segments:
31
31
  - 0
32
- - 4
33
- - 0
34
- version: 0.4.0
32
+ version: "0"
35
33
  type: :runtime
36
34
  version_requirements: *id001
37
35
  - !ruby/object:Gem::Dependency
38
- name: bunny
36
+ name: mixlib-cli
39
37
  prerelease: false
40
38
  requirement: &id002 !ruby/object:Gem::Requirement
41
39
  none: false
42
40
  requirements:
43
- - - "="
41
+ - - ">="
44
42
  - !ruby/object:Gem::Version
45
- hash: 17
43
+ hash: 19
46
44
  segments:
45
+ - 1
46
+ - 1
47
47
  - 0
48
- - 7
49
- - 9
50
- version: 0.7.9
48
+ version: 1.1.0
51
49
  type: :runtime
52
50
  version_requirements: *id002
53
51
  - !ruby/object:Gem::Dependency
54
- name: mixlib-cli
52
+ name: bunny
55
53
  prerelease: false
56
54
  requirement: &id003 !ruby/object:Gem::Requirement
57
55
  none: false
58
56
  requirements:
59
- - - ">="
57
+ - - "="
60
58
  - !ruby/object:Gem::Version
61
- hash: 19
59
+ hash: 17
62
60
  segments:
63
- - 1
64
- - 1
65
61
  - 0
66
- version: 1.1.0
62
+ - 7
63
+ - 9
64
+ version: 0.7.9
67
65
  type: :runtime
68
66
  version_requirements: *id003
69
67
  - !ruby/object:Gem::Dependency
70
- name: json
68
+ name: librato-metrics
71
69
  prerelease: false
72
70
  requirement: &id004 !ruby/object:Gem::Requirement
73
71
  none: false
74
72
  requirements:
75
- - - ">="
73
+ - - "="
76
74
  - !ruby/object:Gem::Version
77
- hash: 3
75
+ hash: 11
78
76
  segments:
79
77
  - 0
80
- version: "0"
78
+ - 4
79
+ - 2
80
+ version: 0.4.2
81
81
  type: :runtime
82
82
  version_requirements: *id004
83
- description: A Graphite Carbon AMQP impostor, sending metrics to Librato Metrics.
83
+ description: A drop-in replacement for Graphite Carbon (TCP & AMQP), sending metrics to Librato Metrics.
84
84
  email:
85
85
  - portertech@gmail.com
86
86
  executables:
@@ -97,6 +97,7 @@ files:
97
97
  - lib/recognizer/librato.rb
98
98
  - lib/recognizer/patches/float.rb
99
99
  - lib/recognizer/patches/hash.rb
100
+ - lib/recognizer/tcp.rb
100
101
  - lib/recognizer/version.rb
101
102
  - lib/recognizer.rb
102
103
  - recognizer.gemspec
@@ -135,6 +136,6 @@ rubyforge_project: recognizer
135
136
  rubygems_version: 1.3.7
136
137
  signing_key:
137
138
  specification_version: 3
138
- summary: A Graphite Carbon AMQP impostor, sending metrics to Librato Metrics.
139
+ summary: A Graphite Carbon impostor, sending metrics to Librato Metrics.
139
140
  test_files: []
140
141