quark 0.0.7 → 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/bin/quark +40 -15
- data/lib/quark.rb +54 -13
- data/lib/quark/commands/fetch.rb +1 -1
- data/lib/quark/commands/observe.rb +1 -1
- data/lib/quark/commands/ping.rb +1 -1
- data/lib/quark/servers/http.rb +70 -0
- metadata +47 -13
data/bin/quark
CHANGED
@@ -7,28 +7,24 @@ module Quark
|
|
7
7
|
class CLI
|
8
8
|
class<<self
|
9
9
|
def run()
|
10
|
-
|
11
|
-
Quark::
|
12
|
-
Quark::Config.set("quark.blocksize", 3600000)
|
13
|
-
Quark::Config.set("quark.udp.enabled", false)
|
14
|
-
Quark::Config.set("quark.graphite_compat", true)
|
15
|
-
Quark::Config.set("debug", false)
|
10
|
+
# sets default options
|
11
|
+
Quark::Server.setup()
|
16
12
|
|
17
13
|
(OptionParser.new do |opts|
|
18
14
|
opts.banner = "Usage: quark [options]"
|
19
15
|
|
20
16
|
# -----------------------------------------------------------------------------
|
21
|
-
opts.on('
|
17
|
+
opts.on('', '--redis-host HOST', 'Hostname of the Redis server to write to') do |host|
|
22
18
|
Quark::Config.set("redis.host", host)
|
23
19
|
end
|
24
20
|
|
25
21
|
# -----------------------------------------------------------------------------
|
26
|
-
opts.on('
|
22
|
+
opts.on('', '--redis-port PORT', 'Hostname of the Redis server to write to') do |port|
|
27
23
|
Quark::Config.set("redis.port", port)
|
28
24
|
end
|
29
25
|
|
30
26
|
# -----------------------------------------------------------------------------
|
31
|
-
opts.on('
|
27
|
+
opts.on('', '--redis-prefix PREFIX', 'The string used to prefix keys in Redis') do |prefix|
|
32
28
|
Quark::Config.set("redis.prefix", prefix)
|
33
29
|
end
|
34
30
|
|
@@ -38,12 +34,12 @@ module Quark
|
|
38
34
|
end
|
39
35
|
|
40
36
|
# -----------------------------------------------------------------------------
|
41
|
-
opts.on('-a', '--
|
37
|
+
opts.on('-a', '--address ADDR', 'The IP address for the TCP server to listen on') do |addr|
|
42
38
|
Quark::Config.set("quark.address", addr)
|
43
39
|
end
|
44
40
|
|
45
41
|
# -----------------------------------------------------------------------------
|
46
|
-
opts.on('-p', '--
|
42
|
+
opts.on('-p', '--port PORT', 'The TCP port to listen on') do |port|
|
47
43
|
Quark::Config.set("quark.port", port)
|
48
44
|
end
|
49
45
|
|
@@ -53,13 +49,23 @@ module Quark
|
|
53
49
|
end
|
54
50
|
|
55
51
|
# -----------------------------------------------------------------------------
|
56
|
-
opts.on('-
|
57
|
-
Quark::Config.set("quark.
|
52
|
+
opts.on('-T', '--[no-]tcp', 'Create a TCP server') do |mode|
|
53
|
+
Quark::Config.set("quark.tcp.enabled", mode)
|
58
54
|
end
|
59
55
|
|
60
56
|
# -----------------------------------------------------------------------------
|
61
|
-
opts.on('
|
62
|
-
Quark::Config.set("
|
57
|
+
opts.on('', '--tcp-address ADDR', 'The IP address for the TCP server to listen on') do |addr|
|
58
|
+
Quark::Config.set("quark.tcp.address", addr)
|
59
|
+
end
|
60
|
+
|
61
|
+
# -----------------------------------------------------------------------------
|
62
|
+
opts.on('', '--tcp-port PORT', 'The TCP port to listen on') do |port|
|
63
|
+
Quark::Config.set("quark.tcp.port", port)
|
64
|
+
end
|
65
|
+
|
66
|
+
# -----------------------------------------------------------------------------
|
67
|
+
opts.on('-U', '--[no-]udp', 'Create a UDP server') do |mode|
|
68
|
+
Quark::Config.set("quark.udp.enabled", mode)
|
63
69
|
end
|
64
70
|
|
65
71
|
# -----------------------------------------------------------------------------
|
@@ -74,6 +80,25 @@ module Quark
|
|
74
80
|
Quark::Config.set("quark.udp.port", port)
|
75
81
|
end
|
76
82
|
|
83
|
+
# -----------------------------------------------------------------------------
|
84
|
+
opts.on('-H', '--[no-]http', 'Create an HTTP server') do |mode|
|
85
|
+
Quark::Config.set("quark.http.enabled", mode)
|
86
|
+
end
|
87
|
+
|
88
|
+
# -----------------------------------------------------------------------------
|
89
|
+
opts.on('', '--http-address ADDR', 'The IP address for the HTTP server to listen on') do |addr|
|
90
|
+
Quark::Config.set("quark.http.address", addr)
|
91
|
+
end
|
92
|
+
|
93
|
+
# -----------------------------------------------------------------------------
|
94
|
+
opts.on('', '--http-port PORT', 'The HTTP port to listen on') do |port|
|
95
|
+
Quark::Config.set("quark.http.port", port)
|
96
|
+
end
|
97
|
+
|
98
|
+
# -----------------------------------------------------------------------------
|
99
|
+
opts.on('-D', '--debug', 'Enable debug mode') do
|
100
|
+
Quark::Config.set("debug", true)
|
101
|
+
end
|
77
102
|
|
78
103
|
# -----------------------------------------------------------------------------
|
79
104
|
opts.on('', '--[no-]graphite', 'Enable/disable Graphite socket compatibility mode') do |mode|
|
data/lib/quark.rb
CHANGED
@@ -5,6 +5,7 @@ require 'hiredis'
|
|
5
5
|
require 'em-synchrony'
|
6
6
|
require 'multi_json'
|
7
7
|
require 'quark/config'
|
8
|
+
require 'quark/servers/http'
|
8
9
|
|
9
10
|
|
10
11
|
module Quark
|
@@ -28,6 +29,14 @@ module Quark
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def receive_data(data)
|
32
|
+
send_json(Quark::SocketServer.process_command(data))
|
33
|
+
end
|
34
|
+
|
35
|
+
def send_json(data)
|
36
|
+
send_data(MultiJson.dump(data)+"\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.process_command(data)
|
31
40
|
# if the data perfectly resembles a graphite-formatted metric (without a command prefix)
|
32
41
|
# then assume the command is "observe"
|
33
42
|
if Quark::Config.get("quark.graphite_compat") and data =~ /^[\w\.\-]+ -?[\d\.]+ \d{10,13}$/
|
@@ -41,32 +50,32 @@ module Quark
|
|
41
50
|
if methods.include?(:"process_command_#{command.downcase}")
|
42
51
|
rv = send(:"process_command_#{command.downcase}", arguments)
|
43
52
|
if rv.nil?
|
44
|
-
|
53
|
+
return {
|
45
54
|
:success => true
|
46
|
-
}
|
55
|
+
}
|
47
56
|
else
|
48
|
-
|
57
|
+
return {
|
49
58
|
:success => true,
|
50
59
|
:command => data.chomp,
|
51
60
|
:results => rv
|
52
|
-
}
|
61
|
+
}
|
53
62
|
end
|
54
63
|
else
|
55
64
|
raise Quark::InvalidCommand.new("Unknown command '#{command.upcase}'")
|
56
65
|
end
|
57
66
|
|
58
67
|
rescue Quark::Error => e
|
59
|
-
|
68
|
+
return {
|
60
69
|
:success => false,
|
61
70
|
:command => data.chomp,
|
62
71
|
:error => {
|
63
72
|
:class => e.class.name,
|
64
73
|
:message => e.message
|
65
74
|
}
|
66
|
-
}
|
75
|
+
}
|
67
76
|
|
68
77
|
rescue Exception => e
|
69
|
-
|
78
|
+
return {
|
70
79
|
:success => false,
|
71
80
|
:command => data.chomp,
|
72
81
|
:error => {
|
@@ -74,34 +83,48 @@ module Quark
|
|
74
83
|
:message => e.message,
|
75
84
|
:backtrace => e.backtrace
|
76
85
|
}
|
77
|
-
}
|
86
|
+
}
|
78
87
|
end
|
79
88
|
end
|
80
89
|
|
81
|
-
def send_json(data)
|
82
|
-
send_data(MultiJson.dump(data)+"\n")
|
83
|
-
end
|
84
|
-
|
85
90
|
def unbind()
|
86
91
|
end
|
87
92
|
end
|
88
93
|
|
89
94
|
class Server
|
95
|
+
def self.setup()
|
96
|
+
Quark::Config.set("quark.address", "127.0.0.1")
|
97
|
+
Quark::Config.set("quark.port", 12161)
|
98
|
+
Quark::Config.set("quark.blocksize", 3600000)
|
99
|
+
Quark::Config.set("quark.tcp.enabled", true)
|
100
|
+
Quark::Config.set("quark.udp.enabled", false)
|
101
|
+
Quark::Config.set("quark.http.enabled", false)
|
102
|
+
Quark::Config.set("quark.http.port", 12180)
|
103
|
+
Quark::Config.get("quark.http.cors", false)
|
104
|
+
Quark::Config.set("quark.graphite_compat", true)
|
105
|
+
Quark::Config.set("debug", false)
|
106
|
+
end
|
107
|
+
|
90
108
|
def self.run()
|
91
109
|
@address = Quark::Config.get("quark.address")
|
92
110
|
@port = Quark::Config.get("quark.port")
|
93
111
|
@filename = Quark::Config.get("quark.socket")
|
94
112
|
|
95
113
|
EM.run do
|
114
|
+
Signal.trap("INT") { Quark::Server.quit() }
|
115
|
+
Signal.trap("TERM") { Quark::Server.quit() }
|
116
|
+
|
96
117
|
if Quark::Config.get("debug")
|
97
118
|
puts "Debug mode is ON"
|
98
119
|
end
|
99
120
|
|
121
|
+
# socket
|
100
122
|
if not @filename.nil? and File.writable?(File.dirname(@filename))
|
101
123
|
puts "Starting socket server at #{@filename}..."
|
102
124
|
EM::start_server(@filename, Quark::SocketServer)
|
103
125
|
end
|
104
126
|
|
127
|
+
# UDP server
|
105
128
|
if Quark::Config.get("quark.udp.enabled") === true
|
106
129
|
@udp_address = Quark::Config.get("quark.udp.address", @address)
|
107
130
|
@udp_port = Quark::Config.get("quark.udp.port", @port)
|
@@ -110,15 +133,33 @@ module Quark
|
|
110
133
|
EM::open_datagram_socket(@udp_address, @udp_port, Quark::SocketServer)
|
111
134
|
end
|
112
135
|
|
113
|
-
|
136
|
+
# TCP server
|
137
|
+
if Quark::Config.get("quark.tcp.enabled") === true
|
114
138
|
puts "Starting TCP server on #{@address}:#{@port}..."
|
115
139
|
EM::start_server(@address, @port, Quark::SocketServer)
|
116
140
|
end
|
117
141
|
|
142
|
+
# HTTP server
|
143
|
+
if Quark::Config.get("quark.http.enabled") === true
|
144
|
+
@http_address = Quark::Config.get("quark.http.address", @address)
|
145
|
+
@http_port = Quark::Config.get("quark.http.port", 12180)
|
146
|
+
|
147
|
+
puts "Starting HTTP server on #{@http_address}:#{@http_port}..."
|
148
|
+
Quark::Server::HttpServer.new({
|
149
|
+
:address => @http_address,
|
150
|
+
:port => @http_port
|
151
|
+
}).run()
|
152
|
+
end
|
153
|
+
|
118
154
|
if Quark::Config.get("quark.graphite_compat")
|
119
155
|
puts "Graphite compatibility mode enabled: all sockets will accept Graphite-formatted metrics as observations"
|
120
156
|
end
|
121
157
|
end
|
122
158
|
end
|
159
|
+
|
160
|
+
def self.quit()
|
161
|
+
puts "Stopping Quark..."
|
162
|
+
EM.stop()
|
163
|
+
end
|
123
164
|
end
|
124
165
|
end
|
data/lib/quark/commands/fetch.rb
CHANGED
data/lib/quark/commands/ping.rb
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Quark
|
2
|
+
class Server
|
3
|
+
class HttpServer
|
4
|
+
require 'sinatra'
|
5
|
+
require 'sinatra/cross_origin'
|
6
|
+
require 'thin'
|
7
|
+
|
8
|
+
class Base < Sinatra::Base
|
9
|
+
configure do
|
10
|
+
mime_type :json, 'application/json'
|
11
|
+
|
12
|
+
if Quark::Config.get("quark.http.cors") === true
|
13
|
+
set :allow_origin, :any
|
14
|
+
set :allow_methods, [:get, :post, :options]
|
15
|
+
set :allow_credentials, true
|
16
|
+
enable :cross_origin
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
if Quark::Config.get("quark.http.cors") === true
|
22
|
+
headers 'Access-Control-Allow-Headers' => 'origin, x-requested-with, accept'
|
23
|
+
end
|
24
|
+
|
25
|
+
content_type :json
|
26
|
+
end
|
27
|
+
|
28
|
+
get '/?' do
|
29
|
+
MultiJson.dump({
|
30
|
+
:status => :ok,
|
31
|
+
:config => Quark::Config.all()
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
get '/call/:command/?*' do
|
36
|
+
MultiJson.dump(Quark::SocketServer.process_command("#{params[:command].upcase} #{params[:splat].first.gsub('/',' ')}".strip))
|
37
|
+
end
|
38
|
+
|
39
|
+
def _quark_command(command, payload)
|
40
|
+
io = nil
|
41
|
+
|
42
|
+
case settings.quark_protocol
|
43
|
+
when :tcp
|
44
|
+
io = TCPSocket.new(settings.quark_host, settings.quark_port)
|
45
|
+
io.puts("#{command.upcase} #{payload}".strip)
|
46
|
+
rv = io.gets()
|
47
|
+
when :socket
|
48
|
+
io = Socket.new(settings.quark_socket)
|
49
|
+
io.puts("#{command.upcase} #{payload}".strip)
|
50
|
+
rv = io.gets()
|
51
|
+
end
|
52
|
+
|
53
|
+
return MultiJson.load(rv)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize(options=nil)
|
58
|
+
@_options = options || Quark::Config.get("quark.http",{})
|
59
|
+
end
|
60
|
+
|
61
|
+
def run()
|
62
|
+
Thin::Logging.silent = true unless Quark::Config.get("debug")
|
63
|
+
Thin::Server.start(@_options.get(:address,'127.0.0.1'), @_options.get(:port, 12180).to_i, Base.new(), {
|
64
|
+
:signals => false,
|
65
|
+
:threaded => true,
|
66
|
+
})
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quark
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2014-05-06 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
16
|
-
requirement: &
|
16
|
+
requirement: &5731120 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - =
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.7.9
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *5731120
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: eventmachine
|
27
|
-
requirement: &
|
27
|
+
requirement: &5730020 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.0.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *5730020
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: redis
|
38
|
-
requirement: &
|
38
|
+
requirement: &5728780 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 3.0.0
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *5728780
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: hiredis
|
49
|
-
requirement: &
|
49
|
+
requirement: &5742700 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.5.2
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *5742700
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: em-synchrony
|
60
|
-
requirement: &
|
60
|
+
requirement: &5739540 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.0.3
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *5739540
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: hashlib
|
71
|
-
requirement: &
|
71
|
+
requirement: &5737440 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,40 @@ dependencies:
|
|
76
76
|
version: 0.0.35
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *5737440
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: sinatra
|
82
|
+
requirement: &5359100 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *5359100
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: sinatra-cross_origin
|
93
|
+
requirement: &5356080 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *5356080
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: thin
|
104
|
+
requirement: &5352680 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *5352680
|
80
113
|
description: A small service for logging and retrieving timeseries metrics into a
|
81
114
|
Redis server
|
82
115
|
email: garyhetzel@gmail.com
|
@@ -86,6 +119,7 @@ extensions: []
|
|
86
119
|
extra_rdoc_files: []
|
87
120
|
files:
|
88
121
|
- lib/quark.rb
|
122
|
+
- lib/quark/servers/http.rb
|
89
123
|
- lib/quark/config.rb
|
90
124
|
- lib/quark/commands/peek.rb
|
91
125
|
- lib/quark/commands/fetch.rb
|