ustate-client 0.0.2 → 0.0.3
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.markdown +94 -12
- data/lib/ustate/emailer.rb +92 -0
- data/lib/ustate/query/and.rb +12 -0
- data/lib/ustate/query/approximately.rb +24 -0
- data/lib/ustate/query/ast.rb +6 -0
- data/lib/ustate/query/equals.rb +12 -0
- data/lib/ustate/query/not.rb +11 -0
- data/lib/ustate/query/not_equals.rb +12 -0
- data/lib/ustate/query/or.rb +12 -0
- data/lib/ustate/query_string.rb +36 -8
- data/lib/ustate/query_string.treetop +29 -1
- data/lib/ustate/server.rb +7 -1
- data/lib/ustate/server/index.rb +35 -2
- data/lib/ustate/state.rb +1 -0
- data/lib/ustate/version.rb +1 -1
- metadata +29 -19
data/README.markdown
CHANGED
@@ -11,10 +11,27 @@ which can be queried or forwarded to various handlers. A state is simply:
|
|
11
11
|
state: Any string less than 255 bytes, e.g. "ok", "warning", "critical",
|
12
12
|
time: The time that the service entered this state, in unix time,
|
13
13
|
description: Freeform text,
|
14
|
-
metric_f: A floating-point number associated with this state, e.g. the number of reqs/sec
|
14
|
+
metric_f: A floating-point number associated with this state, e.g. the number of reqs/sec,
|
15
|
+
once: A boolean, described below.
|
15
16
|
}
|
16
17
|
|
17
|
-
|
18
|
+
Normally, every state received by the server fires Index#on_state. When
|
19
|
+
state.state changes, Index#on_state_change is called. You can, for example,
|
20
|
+
register to send a single email whenever a state changes to :warning.
|
21
|
+
|
22
|
+
:once states are transient. They fire Index#on_state and #on_state_once, but do
|
23
|
+
*not* update the index. They can be used for events which are instantaneous;
|
24
|
+
instead of sending {state: error} and {state: ok}, send {state: error,
|
25
|
+
once:true}.
|
26
|
+
|
27
|
+
For example, recoverable errors may not hang your application, but
|
28
|
+
should be processed by the email notifier. Sending a :once state with
|
29
|
+
the error description means you can receive an email for each error,
|
30
|
+
instead of two for entering and exiting the error state.
|
31
|
+
|
32
|
+
At http://showyou.com, we use UState to monitor the health and performance of
|
33
|
+
hundreds of services across our infrastructure, including CPU, queries/second,
|
34
|
+
latency bounds, disk usage, queues, and others.
|
18
35
|
|
19
36
|
UState also includes a simple dashboard Sinatra app.
|
20
37
|
|
@@ -39,22 +56,89 @@ For the dashboard:
|
|
39
56
|
|
40
57
|
gem install sinatra thin erubis sass
|
41
58
|
|
42
|
-
|
43
|
-
|
59
|
+
Demo
|
60
|
+
====
|
44
61
|
|
45
62
|
To try it out, install all the gems above, and clone the repository. Start the server with
|
46
63
|
|
47
|
-
bin/server
|
64
|
+
bin/server
|
48
65
|
|
49
66
|
UState listens on TCP socket host:port, and accepts connections from clients. Start a basic testing client with
|
50
67
|
|
51
|
-
|
68
|
+
bin/test
|
52
69
|
|
53
70
|
The tester spews randomly generated statistics at a server on the default local host and port. To see it in action, run the dashboard:
|
54
71
|
|
55
|
-
|
56
|
-
|
72
|
+
cd lib/ustate/dash
|
73
|
+
../../../bin/dash
|
74
|
+
|
75
|
+
Server
|
76
|
+
======
|
77
|
+
|
78
|
+
The server loads a file in the working directory named config.rb. Override with
|
79
|
+
--config-file. Its contents are instance-evaled in the context of the current
|
80
|
+
server. You can use this to extend ustate with additional behavior.
|
81
|
+
|
82
|
+
Email
|
83
|
+
-----
|
84
|
+
|
85
|
+
config.rb:
|
86
|
+
# Email comes from this address (required):
|
87
|
+
emailer.from = 'ustate@your.net'
|
88
|
+
|
89
|
+
# Use this SMTP relay (default 127.0.0.1)
|
90
|
+
emailer.host = '123.4.56.7'
|
91
|
+
|
92
|
+
# Receive mail when a state transition matches any of ...
|
93
|
+
emailer.tell 'you@gmail.com', 'state = "error" or state = "critical"'
|
94
|
+
emailer.tell 'you@gmail.com', 'service =~ "mysql%"'
|
95
|
+
|
96
|
+
Custom hooks
|
97
|
+
------------
|
98
|
+
|
99
|
+
config.rb:
|
100
|
+
# Log all states received to console.
|
101
|
+
index.on_state do |s|
|
102
|
+
p s
|
103
|
+
end
|
104
|
+
|
105
|
+
# Forward state transitions to another server.
|
106
|
+
require 'ustate/client'
|
107
|
+
client = UState::Client.new :host => '123.45.67.8'
|
108
|
+
index.on_state_change do |old, new|
|
109
|
+
client << new
|
110
|
+
end
|
111
|
+
index.on_state_once do |state|
|
112
|
+
client << state
|
113
|
+
end
|
114
|
+
|
115
|
+
Client
|
116
|
+
======
|
57
117
|
|
118
|
+
You can use the git repo, or the gem.
|
119
|
+
|
120
|
+
gem install ustate-client
|
121
|
+
|
122
|
+
Then:
|
123
|
+
|
124
|
+
require 'ustate'
|
125
|
+
require 'ustate/client'
|
126
|
+
|
127
|
+
# Create a client
|
128
|
+
c = UState::Client.new(
|
129
|
+
host: "my.host", # Default localhost
|
130
|
+
port: 1234 # Default 55956
|
131
|
+
)
|
132
|
+
|
133
|
+
# Insert a state
|
134
|
+
c << {
|
135
|
+
state: "ok",
|
136
|
+
service: "My service"
|
137
|
+
}
|
138
|
+
|
139
|
+
# Query for states
|
140
|
+
c.query.states # => [UState::State(state: 'ok', service: 'My service')]
|
141
|
+
c.query('state != "ok"').states # => []
|
58
142
|
|
59
143
|
The Dashboard
|
60
144
|
=============
|
@@ -90,20 +174,18 @@ You can also query states using a very basic expression language. The grammar is
|
|
90
174
|
state = "ok"
|
91
175
|
(service =~ "disk%") or (state == "critical" and host =~ "%.trioptimum.com")
|
92
176
|
|
93
|
-
Search queries will return a message with repeated States matching that expression. An
|
177
|
+
Search queries will return a message with repeated States matching that expression. An null expression will return no states.
|
94
178
|
|
95
179
|
Performance
|
96
180
|
===========
|
97
181
|
|
98
|
-
|
182
|
+
On a macbook pro 8,3, I see >1300 queries/sec or >1200 inserts/sec. The client is fully threadsafe, and performs well concurrently. I will continue to tune UState for latency and throughput, and welcome patches.
|
99
183
|
|
100
184
|
For large installations, I plan to implement a selective forwarder. Local ustate servers can accept high volumes of states from a small set of nodes, and forward updates at a larger granularity to supervisors, and so forth, in a tree. The query language should be able to support proxying requests to the most recent source of a state, so very large sets of services can be maintained at high granularity.
|
101
185
|
|
102
186
|
Goals
|
103
187
|
=====
|
104
188
|
|
105
|
-
Immediately, I'll be porting our internal email alerter to UState. Users register for interest in certain types of states or transitions, and receive emails when those events occur.
|
106
|
-
|
107
189
|
In the medium term, I'll be connecting UState to Graphite (or perhaps another
|
108
190
|
graphing tool) for metrics archival and soft-realtime graphs. I have an
|
109
191
|
internal gnuplot system which is clunky and deserves retirement.
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module UState
|
2
|
+
class Emailer
|
3
|
+
require 'net/smtp'
|
4
|
+
|
5
|
+
attr_accessor :from
|
6
|
+
attr_accessor :host
|
7
|
+
attr_accessor :name
|
8
|
+
|
9
|
+
# Registers self with index.
|
10
|
+
# Options:
|
11
|
+
# :host: The SMTP host to connect to. Default 'localhost'
|
12
|
+
# :name: The From name used. Default "ustate".
|
13
|
+
# :from: The From address used: e.g. "ustate@your_domain.com"
|
14
|
+
def initialize(index, opts = {})
|
15
|
+
opts = {
|
16
|
+
:name => 'ustate',
|
17
|
+
:host => 'localhost'
|
18
|
+
}.merge opts
|
19
|
+
|
20
|
+
@from = opts[:from]
|
21
|
+
@name = opts[:name]
|
22
|
+
@host = opts[:host]
|
23
|
+
|
24
|
+
@tell = {}
|
25
|
+
|
26
|
+
index.on_state_change &method(:receive)
|
27
|
+
index.on_state_once &method(:receive)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Send an email to address about state.
|
31
|
+
def email(address, s)
|
32
|
+
raise ArgumentError, "no from address" unless @from
|
33
|
+
|
34
|
+
# Subject
|
35
|
+
subject = "#{s.host} #{s.service} #{s.state}"
|
36
|
+
if s.once
|
37
|
+
subject << " transient "
|
38
|
+
else
|
39
|
+
subject << " is "
|
40
|
+
end
|
41
|
+
subject << s.state
|
42
|
+
|
43
|
+
# Body
|
44
|
+
body = "#{subject}: #{s.description}"
|
45
|
+
|
46
|
+
# SMTP message
|
47
|
+
message = <<EOF
|
48
|
+
From: #{@name} <#{@from}>
|
49
|
+
To: <#{address}>
|
50
|
+
Subject: #{subject.gsub("\n", ' ')}
|
51
|
+
|
52
|
+
#{body}
|
53
|
+
EOF
|
54
|
+
|
55
|
+
Net::SMTP.start(@host) do |smtp|
|
56
|
+
smtp.send_message message, @from, address
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Dispatch emails to each address which is interested in this state
|
61
|
+
def receive(*states)
|
62
|
+
state = states.last
|
63
|
+
Thread.new do
|
64
|
+
@tell.each do |address, q|
|
65
|
+
if q === state
|
66
|
+
email address, state
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Notify email when a state matching query_string is
|
73
|
+
# received. Multiple calls are ORed together:
|
74
|
+
#
|
75
|
+
# emailer.tell 'aphyr@aphyr.com', 'state = "error"'
|
76
|
+
# emailer.tell 'aphyr@aphyr.com', 'host =~ "frontend%"'
|
77
|
+
def tell(email, query_string)
|
78
|
+
parser = QueryStringParser.new
|
79
|
+
q = parser.parse(query_string)
|
80
|
+
unless q
|
81
|
+
raise ArgumentError, "error parsing #{query_string.inspect} at line #{parser.failure_line}:#{parser.failure_column}: #{parser.failure_reason}"
|
82
|
+
end
|
83
|
+
q = q.query
|
84
|
+
|
85
|
+
@tell[email] = if existing = @tell[email]
|
86
|
+
Query::Or.new existing, q
|
87
|
+
else
|
88
|
+
q
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class UState::Query
|
2
|
+
class Approximately
|
3
|
+
def initialize(field, value)
|
4
|
+
@field = field
|
5
|
+
@value = case value
|
6
|
+
when String
|
7
|
+
r = value.chars.inject('') do |r, c|
|
8
|
+
if c == '%'
|
9
|
+
r << '.*'
|
10
|
+
else
|
11
|
+
r << Regexp.escape(c)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
/^#{r}$/
|
15
|
+
else
|
16
|
+
value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ===(state)
|
21
|
+
@value === state.send(@field)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/ustate/query_string.rb
CHANGED
@@ -34,6 +34,12 @@ module UState
|
|
34
34
|
end
|
35
35
|
|
36
36
|
module Or2
|
37
|
+
def query
|
38
|
+
rest.elements.map { |x| x.and }.inject(first.query) do |a, sub|
|
39
|
+
Query::Or.new a, sub.query
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
37
43
|
def sql
|
38
44
|
rest.elements.map { |x| x.and }.
|
39
45
|
inject(first.sql) do |a, sub|
|
@@ -135,6 +141,12 @@ module UState
|
|
135
141
|
end
|
136
142
|
|
137
143
|
module And2
|
144
|
+
def query
|
145
|
+
rest.elements.map { |x| x.primary }.inject(first.query) do |a, sub|
|
146
|
+
Query::And.new a, sub.query
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
138
150
|
def sql
|
139
151
|
rest.elements.map { |x| x.primary }.
|
140
152
|
inject(first.sql) do |a, sub|
|
@@ -219,6 +231,10 @@ module UState
|
|
219
231
|
end
|
220
232
|
|
221
233
|
module Primary1
|
234
|
+
def query
|
235
|
+
x.query
|
236
|
+
end
|
237
|
+
|
222
238
|
def sql
|
223
239
|
x.sql
|
224
240
|
end
|
@@ -348,6 +364,10 @@ module UState
|
|
348
364
|
end
|
349
365
|
|
350
366
|
module Approximately1
|
367
|
+
def query
|
368
|
+
Query::Approximately.new field.sql, string.sql
|
369
|
+
end
|
370
|
+
|
351
371
|
def sql
|
352
372
|
Sequel::SQL::StringExpression.like field.sql, string.sql
|
353
373
|
end
|
@@ -424,6 +444,10 @@ module UState
|
|
424
444
|
end
|
425
445
|
|
426
446
|
module NotEquals1
|
447
|
+
def query
|
448
|
+
Query::NotEquals.new field.sql, value.sql
|
449
|
+
end
|
450
|
+
|
427
451
|
def sql
|
428
452
|
Sequel::SQL::BooleanExpression.from_value_pairs({field.sql => value.sql}, :AND, true)
|
429
453
|
end
|
@@ -500,6 +524,10 @@ module UState
|
|
500
524
|
end
|
501
525
|
|
502
526
|
module Equals1
|
527
|
+
def query
|
528
|
+
Query::Equals.new field.sql, value.sql
|
529
|
+
end
|
530
|
+
|
503
531
|
def sql
|
504
532
|
Sequel::SQL::BooleanExpression.from_value_pairs field.sql => value.sql
|
505
533
|
end
|
@@ -529,21 +557,21 @@ module UState
|
|
529
557
|
s0 << r2
|
530
558
|
if r2
|
531
559
|
i4 = index
|
532
|
-
if has_terminal?('
|
533
|
-
r5 = instantiate_node(SyntaxNode,input, index...(index +
|
534
|
-
@index +=
|
560
|
+
if has_terminal?('==', false, index)
|
561
|
+
r5 = instantiate_node(SyntaxNode,input, index...(index + 2))
|
562
|
+
@index += 2
|
535
563
|
else
|
536
|
-
terminal_parse_failure('
|
564
|
+
terminal_parse_failure('==')
|
537
565
|
r5 = nil
|
538
566
|
end
|
539
567
|
if r5
|
540
568
|
r4 = r5
|
541
569
|
else
|
542
|
-
if has_terminal?('
|
543
|
-
r6 = instantiate_node(SyntaxNode,input, index...(index +
|
544
|
-
@index +=
|
570
|
+
if has_terminal?('=', false, index)
|
571
|
+
r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
572
|
+
@index += 1
|
545
573
|
else
|
546
|
-
terminal_parse_failure('
|
574
|
+
terminal_parse_failure('=')
|
547
575
|
r6 = nil
|
548
576
|
end
|
549
577
|
if r6
|
@@ -5,6 +5,12 @@ module UState
|
|
5
5
|
|
6
6
|
rule or
|
7
7
|
first:and rest:(space 'or' space and)* {
|
8
|
+
def query
|
9
|
+
rest.elements.map { |x| x.and }.inject(first.query) do |a, sub|
|
10
|
+
Query::Or.new a, sub.query
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
8
14
|
def sql
|
9
15
|
rest.elements.map { |x| x.and }.
|
10
16
|
inject(first.sql) do |a, sub|
|
@@ -16,6 +22,12 @@ module UState
|
|
16
22
|
|
17
23
|
rule and
|
18
24
|
first:primary rest:(space 'and' space primary)* {
|
25
|
+
def query
|
26
|
+
rest.elements.map { |x| x.primary }.inject(first.query) do |a, sub|
|
27
|
+
Query::And.new a, sub.query
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
19
31
|
def sql
|
20
32
|
rest.elements.map { |x| x.primary }.
|
21
33
|
inject(first.sql) do |a, sub|
|
@@ -27,6 +39,10 @@ module UState
|
|
27
39
|
|
28
40
|
rule primary
|
29
41
|
'(' space? x:or space? ')' {
|
42
|
+
def query
|
43
|
+
x.query
|
44
|
+
end
|
45
|
+
|
30
46
|
def sql
|
31
47
|
x.sql
|
32
48
|
end
|
@@ -41,6 +57,10 @@ module UState
|
|
41
57
|
|
42
58
|
rule approximately
|
43
59
|
field space? '=~' space? string {
|
60
|
+
def query
|
61
|
+
Query::Approximately.new field.sql, string.sql
|
62
|
+
end
|
63
|
+
|
44
64
|
def sql
|
45
65
|
Sequel::SQL::StringExpression.like field.sql, string.sql
|
46
66
|
end
|
@@ -49,6 +69,10 @@ module UState
|
|
49
69
|
|
50
70
|
rule not_equals
|
51
71
|
field space? '!=' space? value {
|
72
|
+
def query
|
73
|
+
Query::NotEquals.new field.sql, value.sql
|
74
|
+
end
|
75
|
+
|
52
76
|
def sql
|
53
77
|
Sequel::SQL::BooleanExpression.from_value_pairs({field.sql => value.sql}, :AND, true)
|
54
78
|
end
|
@@ -56,7 +80,11 @@ module UState
|
|
56
80
|
end
|
57
81
|
|
58
82
|
rule equals
|
59
|
-
field space? ('
|
83
|
+
field space? ('==' / '=') space? value {
|
84
|
+
def query
|
85
|
+
Query::Equals.new field.sql, value.sql
|
86
|
+
end
|
87
|
+
|
60
88
|
def sql
|
61
89
|
Sequel::SQL::BooleanExpression.from_value_pairs field.sql => value.sql
|
62
90
|
end
|
data/lib/ustate/server.rb
CHANGED
@@ -12,7 +12,8 @@ module UState
|
|
12
12
|
require 'ustate/server/index'
|
13
13
|
require 'ustate/server/backends'
|
14
14
|
require 'treetop'
|
15
|
-
require 'ustate/query_string
|
15
|
+
require 'ustate/query_string'
|
16
|
+
require 'ustate/query/ast'
|
16
17
|
|
17
18
|
attr_accessor :backends
|
18
19
|
attr_accessor :index
|
@@ -29,6 +30,11 @@ module UState
|
|
29
30
|
setup_signals
|
30
31
|
end
|
31
32
|
|
33
|
+
def emailer(opts = {})
|
34
|
+
require 'ustate/emailer'
|
35
|
+
@emailer ||= UState::Emailer.new(@index, opts)
|
36
|
+
end
|
37
|
+
|
32
38
|
def start
|
33
39
|
@index.start
|
34
40
|
|
data/lib/ustate/server/index.rb
CHANGED
@@ -19,6 +19,10 @@ module UState
|
|
19
19
|
@threads = opts[:threads] || THREADS
|
20
20
|
@pool = []
|
21
21
|
|
22
|
+
@on_state_change = []
|
23
|
+
@on_state_once = []
|
24
|
+
@on_state = []
|
25
|
+
|
22
26
|
setup_db
|
23
27
|
end
|
24
28
|
|
@@ -39,13 +43,42 @@ module UState
|
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
|
-
def on_state_change(old, new)
|
46
|
+
def on_state_change(old = nil, new = nil, &block)
|
47
|
+
if block_given?
|
48
|
+
@on_state_change |= [block]
|
49
|
+
else
|
50
|
+
@on_state_change.each do |callback|
|
51
|
+
callback.call old, new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def on_state_once(state = nil, &block)
|
57
|
+
if block_given?
|
58
|
+
@on_state_once |= [block]
|
59
|
+
else
|
60
|
+
@on_state_once.each do |callback|
|
61
|
+
callback.call state
|
62
|
+
end
|
63
|
+
end
|
43
64
|
end
|
44
65
|
|
45
|
-
def on_state(state)
|
66
|
+
def on_state(state = nil, &block)
|
67
|
+
if block_given?
|
68
|
+
@on_state |= [block]
|
69
|
+
else
|
70
|
+
@on_state.each do |callback|
|
71
|
+
callback.call state
|
72
|
+
end
|
73
|
+
end
|
46
74
|
end
|
47
75
|
|
48
76
|
def process(s)
|
77
|
+
if s.once
|
78
|
+
on_state_once s
|
79
|
+
return on_state s
|
80
|
+
end
|
81
|
+
|
49
82
|
if current = @db[:states][host: s.host, service: s.service]
|
50
83
|
# Update
|
51
84
|
if current[:time] <= s.time
|
data/lib/ustate/state.rb
CHANGED
data/lib/ustate/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ustate-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-06 00:00:00.000000000 -07:00
|
13
|
+
default_executable:
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: beefcake
|
16
|
-
requirement: &
|
17
|
+
requirement: &15107700 !ruby/object:Gem::Requirement
|
17
18
|
none: false
|
18
19
|
requirements:
|
19
20
|
- - ! '>='
|
@@ -21,10 +22,10 @@ dependencies:
|
|
21
22
|
version: 0.3.5
|
22
23
|
type: :runtime
|
23
24
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
+
version_requirements: *15107700
|
25
26
|
- !ruby/object:Gem::Dependency
|
26
27
|
name: trollop
|
27
|
-
requirement: &
|
28
|
+
requirement: &15107220 !ruby/object:Gem::Requirement
|
28
29
|
none: false
|
29
30
|
requirements:
|
30
31
|
- - ! '>='
|
@@ -32,7 +33,7 @@ dependencies:
|
|
32
33
|
version: 1.16.2
|
33
34
|
type: :runtime
|
34
35
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
+
version_requirements: *15107220
|
36
37
|
description:
|
37
38
|
email: aphyr@aphyr.com
|
38
39
|
executables: []
|
@@ -40,32 +41,41 @@ extensions: []
|
|
40
41
|
extra_rdoc_files: []
|
41
42
|
files:
|
42
43
|
- lib/ustate.rb
|
44
|
+
- lib/ustate/query/not_equals.rb
|
45
|
+
- lib/ustate/query/equals.rb
|
46
|
+
- lib/ustate/query/or.rb
|
47
|
+
- lib/ustate/query/approximately.rb
|
48
|
+
- lib/ustate/query/and.rb
|
49
|
+
- lib/ustate/query/ast.rb
|
50
|
+
- lib/ustate/query/not.rb
|
43
51
|
- lib/ustate/query_string.treetop
|
44
|
-
- lib/ustate/
|
52
|
+
- lib/ustate/server.rb
|
53
|
+
- lib/ustate/emailer.rb
|
54
|
+
- lib/ustate/query.rb
|
45
55
|
- lib/ustate/version.rb
|
46
|
-
- lib/ustate/
|
56
|
+
- lib/ustate/state.rb
|
57
|
+
- lib/ustate/client/query.rb
|
58
|
+
- lib/ustate/query_string.rb
|
59
|
+
- lib/ustate/server/index.rb
|
47
60
|
- lib/ustate/server/backends.rb
|
48
|
-
- lib/ustate/server/backends/base.rb
|
49
61
|
- lib/ustate/server/backends/tcp.rb
|
50
|
-
- lib/ustate/server/
|
62
|
+
- lib/ustate/server/backends/base.rb
|
63
|
+
- lib/ustate/server/graphite.rb
|
51
64
|
- lib/ustate/server/connection.rb
|
52
|
-
- lib/ustate/server.rb
|
53
|
-
- lib/ustate/dash.rb
|
54
|
-
- lib/ustate/state.rb
|
55
|
-
- lib/ustate/query.rb
|
56
|
-
- lib/ustate/client/query.rb
|
57
65
|
- lib/ustate/client.rb
|
66
|
+
- lib/ustate/message.rb
|
67
|
+
- lib/ustate/dash/helper/renderer.rb
|
68
|
+
- lib/ustate/dash/views/css.scss
|
58
69
|
- lib/ustate/dash/views/index.erubis
|
59
70
|
- lib/ustate/dash/views/layout.erubis
|
60
|
-
- lib/ustate/dash/views/css.scss
|
61
71
|
- lib/ustate/dash/state.rb
|
62
72
|
- lib/ustate/dash/controller/index.rb
|
63
73
|
- lib/ustate/dash/controller/css.rb
|
64
74
|
- lib/ustate/dash/config.rb
|
65
|
-
- lib/ustate/dash
|
66
|
-
- lib/ustate/query_string.rb
|
75
|
+
- lib/ustate/dash.rb
|
67
76
|
- LICENSE
|
68
77
|
- README.markdown
|
78
|
+
has_rdoc: true
|
69
79
|
homepage: https://github.com/aphyr/ustate
|
70
80
|
licenses: []
|
71
81
|
post_install_message:
|
@@ -86,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
96
|
version: '0'
|
87
97
|
requirements: []
|
88
98
|
rubyforge_project: ustate-client
|
89
|
-
rubygems_version: 1.
|
99
|
+
rubygems_version: 1.6.2
|
90
100
|
signing_key:
|
91
101
|
specification_version: 3
|
92
102
|
summary: Client for the distributed state server ustate.
|