ustate-client 0.0.4 → 0.0.5
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 +10 -0
- data/lib/ustate/aggregator.rb +17 -11
- data/lib/ustate/auto_state.rb +125 -0
- data/lib/ustate/client.rb +9 -3
- data/lib/ustate/dash/helper/renderer.rb +14 -4
- data/lib/ustate/emailer.rb +8 -3
- data/lib/ustate/graphite.rb +9 -3
- data/lib/ustate/server.rb +11 -5
- data/lib/ustate/server/backends/base.rb +1 -0
- data/lib/ustate/server/backends/tcp.rb +1 -1
- data/lib/ustate/server/index.rb +1 -0
- data/lib/ustate/state.rb +17 -14
- data/lib/ustate/version.rb +1 -1
- metadata +9 -8
data/README.markdown
CHANGED
@@ -187,6 +187,16 @@ Then:
|
|
187
187
|
c.query.states # => [UState::State(state: 'ok', service: 'My service')]
|
188
188
|
c.query('state != "ok"').states # => []
|
189
189
|
|
190
|
+
Client state management
|
191
|
+
-----------------------
|
192
|
+
|
193
|
+
UState provides some classes to make managing state updates easier.
|
194
|
+
|
195
|
+
UState::MetricThread starts a thread to poll a metric periodically, which can
|
196
|
+
be used to flush an accumulated value to ustate at regular intervals.
|
197
|
+
|
198
|
+
UState::AutoState bundles a state and a client together. Any changes to the AutoState automatically send the new state to the client.
|
199
|
+
|
190
200
|
The Dashboard
|
191
201
|
=============
|
192
202
|
|
data/lib/ustate/aggregator.rb
CHANGED
@@ -11,14 +11,15 @@ module UState
|
|
11
11
|
|
12
12
|
@folds = {}
|
13
13
|
@interval = opts[:interval] || INTERVAL
|
14
|
+
@server = opts[:server]
|
14
15
|
|
15
16
|
start
|
16
17
|
end
|
17
18
|
|
18
19
|
# Combines states matching query with State.average
|
19
|
-
def average(query,
|
20
|
+
def average(query, *a)
|
20
21
|
fold query do |states|
|
21
|
-
State.average states,
|
22
|
+
State.average states, *a
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -45,24 +46,29 @@ module UState
|
|
45
46
|
def start
|
46
47
|
@runner = Thread.new do
|
47
48
|
loop do
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
begin
|
50
|
+
interval = (@interval.to_f / @folds.size) rescue @interval
|
51
|
+
@folds.each do |f, query|
|
52
|
+
matching = @index.query(Query.new(string: query))
|
53
|
+
unless matching.empty?
|
54
|
+
if combined = f[matching]
|
55
|
+
@index << combined
|
56
|
+
end
|
54
57
|
end
|
58
|
+
sleep interval
|
55
59
|
end
|
56
|
-
|
60
|
+
rescue Exception => e
|
61
|
+
@server.log.error e
|
62
|
+
sleep 1
|
57
63
|
end
|
58
64
|
end
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
68
|
# Combines states matching query with State.sum
|
63
|
-
def sum(query,
|
69
|
+
def sum(query, *a)
|
64
70
|
fold query do |states|
|
65
|
-
State.sum states,
|
71
|
+
State.sum states, *a
|
66
72
|
end
|
67
73
|
end
|
68
74
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module UState
|
2
|
+
class AutoState
|
3
|
+
# Binds together a State and a Client. Any change made here
|
4
|
+
# sends the state to the client. Useful when updates to a state are made
|
5
|
+
# decoherently, e.g. across many methods. Combine with MetricThread (or
|
6
|
+
# just Thread.new { loop { autostate.flush; sleep n } }) to ensure regular
|
7
|
+
# updates.
|
8
|
+
#
|
9
|
+
# example:
|
10
|
+
#
|
11
|
+
# class Job
|
12
|
+
# def initialize
|
13
|
+
# @state = AutoState.new
|
14
|
+
# @state.service = 'job'
|
15
|
+
# @state.state = 'starting up'
|
16
|
+
#
|
17
|
+
# run
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def run
|
21
|
+
# loop do
|
22
|
+
# begin
|
23
|
+
# a
|
24
|
+
# b
|
25
|
+
# rescue Exception => e
|
26
|
+
# @state.once(
|
27
|
+
# state: 'error',
|
28
|
+
# description: e.to_s
|
29
|
+
# )
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# def a
|
35
|
+
# @state.state = 'heavy lifting a'
|
36
|
+
# ...
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# def b
|
40
|
+
# @state.state = 'heavy lifting b'
|
41
|
+
# ...
|
42
|
+
# end
|
43
|
+
|
44
|
+
def initialize(client = Client.new, state = State.new)
|
45
|
+
@client = client
|
46
|
+
@state = case state
|
47
|
+
when State
|
48
|
+
state
|
49
|
+
else
|
50
|
+
State.new state
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def description=(description)
|
55
|
+
@state.description = description
|
56
|
+
flush
|
57
|
+
end
|
58
|
+
|
59
|
+
def description
|
60
|
+
@state.description
|
61
|
+
end
|
62
|
+
|
63
|
+
# Send state to client
|
64
|
+
def flush
|
65
|
+
@client << @state
|
66
|
+
end
|
67
|
+
|
68
|
+
def host=(host)
|
69
|
+
@state.host = host
|
70
|
+
flush
|
71
|
+
end
|
72
|
+
|
73
|
+
def host
|
74
|
+
@state.host
|
75
|
+
end
|
76
|
+
|
77
|
+
def metric_f=(metric_f)
|
78
|
+
@state.metric_f = metric_f
|
79
|
+
flush
|
80
|
+
end
|
81
|
+
|
82
|
+
def metric_f
|
83
|
+
@state.metric_f
|
84
|
+
end
|
85
|
+
|
86
|
+
# Performs multiple updates, followed by flush.
|
87
|
+
# Example: merge state: critical, metric_f: 10235.3
|
88
|
+
def merge(opts)
|
89
|
+
opts.each do |k, v|
|
90
|
+
@state.send "#{k}=", v
|
91
|
+
end
|
92
|
+
flush
|
93
|
+
end
|
94
|
+
|
95
|
+
# Issues an immediate update of the state with the :once option
|
96
|
+
# set, but does not update the local state. Useful for transient errors.
|
97
|
+
# Opts are merged with the state.
|
98
|
+
def once(opts)
|
99
|
+
o = @state.dup
|
100
|
+
opts.each do |k, v|
|
101
|
+
o.send "#{k}=", v
|
102
|
+
end
|
103
|
+
o.once = true
|
104
|
+
@client << o
|
105
|
+
end
|
106
|
+
|
107
|
+
def state=(state)
|
108
|
+
@state.state = state
|
109
|
+
flush
|
110
|
+
end
|
111
|
+
|
112
|
+
def state
|
113
|
+
@state.state
|
114
|
+
end
|
115
|
+
|
116
|
+
def service=(service)
|
117
|
+
@state.service = service
|
118
|
+
flush
|
119
|
+
end
|
120
|
+
|
121
|
+
def service
|
122
|
+
@state.service
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/ustate/client.rb
CHANGED
@@ -23,9 +23,15 @@ class UState::Client
|
|
23
23
|
# Send a state
|
24
24
|
def <<(state_opts)
|
25
25
|
# Create state
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
case state_opts
|
27
|
+
when UState::State
|
28
|
+
state = state_opts
|
29
|
+
else
|
30
|
+
unless state_opts.include? :host
|
31
|
+
state_opts[:host] = Socket.gethostname
|
32
|
+
end
|
33
|
+
state = UState::State.new(state_opts)
|
34
|
+
end
|
29
35
|
|
30
36
|
message = UState::Message.new :states => [state]
|
31
37
|
|
@@ -125,14 +125,16 @@ module UState
|
|
125
125
|
|
126
126
|
# Compute maximum for each service
|
127
127
|
maxima = if o[:global_maximum]
|
128
|
-
max = states.map(&:metric).max
|
128
|
+
max = states.map(&:metric).compact.max
|
129
129
|
services.inject({}) do |m, s|
|
130
130
|
m[s] = max
|
131
131
|
m
|
132
132
|
end.merge o[:maxima]
|
133
133
|
else
|
134
134
|
states.inject(Hash.new(0)) do |m, s|
|
135
|
-
|
135
|
+
if s.metric
|
136
|
+
m[s.service] = [s.metric, m[s.service]].max
|
137
|
+
end
|
136
138
|
m
|
137
139
|
end.merge o[:maxima]
|
138
140
|
end
|
@@ -141,8 +143,16 @@ module UState
|
|
141
143
|
# list of hosts explicitly given.
|
142
144
|
hosts = o[:hosts] || states.map do |state|
|
143
145
|
state.host
|
144
|
-
end
|
145
|
-
hosts = hosts.uniq.sort
|
146
|
+
end
|
147
|
+
hosts = hosts.uniq.sort { |a, b|
|
148
|
+
if !a
|
149
|
+
-1
|
150
|
+
elsif !b
|
151
|
+
1
|
152
|
+
else
|
153
|
+
a <=> b
|
154
|
+
end
|
155
|
+
}
|
146
156
|
|
147
157
|
# Construct index
|
148
158
|
by = states.inject({}) do |index, s|
|
data/lib/ustate/emailer.rb
CHANGED
@@ -23,6 +23,7 @@ module UState
|
|
23
23
|
@from = opts[:from]
|
24
24
|
@name = opts[:name]
|
25
25
|
@host = opts[:host]
|
26
|
+
@server = opts[:server]
|
26
27
|
|
27
28
|
@tell = {}
|
28
29
|
|
@@ -63,10 +64,14 @@ EOF
|
|
63
64
|
# Dispatch emails to each address which is interested in this state
|
64
65
|
def receive(*states)
|
65
66
|
Thread.new do
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
begin
|
68
|
+
@tell.each do |address, q|
|
69
|
+
if states.any? { |state| p state; q === state }
|
70
|
+
email address, states.last
|
71
|
+
end
|
69
72
|
end
|
73
|
+
rescue Exception => e
|
74
|
+
@server.log.error e
|
70
75
|
end
|
71
76
|
end
|
72
77
|
end
|
data/lib/ustate/graphite.rb
CHANGED
@@ -15,6 +15,7 @@ module UState
|
|
15
15
|
@query = opts[:query]
|
16
16
|
@host = opts[:host] || HOST
|
17
17
|
@port = opts[:port] || PORT
|
18
|
+
@server = opts[:server]
|
18
19
|
@interval = opts[:interval] || INTERVAL
|
19
20
|
@locket = Mutex.new
|
20
21
|
|
@@ -68,10 +69,15 @@ module UState
|
|
68
69
|
def start
|
69
70
|
@runner = Thread.new do
|
70
71
|
loop do
|
71
|
-
|
72
|
-
|
72
|
+
begin
|
73
|
+
@index.query(Query.new(string: @query)).each do |state|
|
74
|
+
forward state
|
75
|
+
end
|
76
|
+
sleep @interval
|
77
|
+
rescue Exception => e
|
78
|
+
@server.log.warn e
|
79
|
+
sleep 1
|
73
80
|
end
|
74
|
-
sleep @interval
|
75
81
|
end
|
76
82
|
end
|
77
83
|
end
|
data/lib/ustate/server.rb
CHANGED
@@ -15,6 +15,7 @@ module UState
|
|
15
15
|
require 'ustate/query_string'
|
16
16
|
require 'ustate/query/ast'
|
17
17
|
require 'ustate/metric_thread'
|
18
|
+
require 'logger'
|
18
19
|
require 'mtrc'
|
19
20
|
|
20
21
|
attr_accessor :backends
|
@@ -22,32 +23,37 @@ module UState
|
|
22
23
|
attr_writer :aggregator
|
23
24
|
attr_writer :emailer
|
24
25
|
attr_writer :graphite
|
26
|
+
|
27
|
+
attr_accessor :log
|
25
28
|
|
26
29
|
def initialize(opts = {})
|
27
30
|
# Backends
|
28
31
|
@backends = []
|
29
|
-
b = Backends::TCP.new opts
|
32
|
+
b = Backends::TCP.new opts.merge(server: self)
|
30
33
|
b.server = self
|
31
34
|
@backends << b
|
32
35
|
|
33
|
-
@index = Index.new
|
36
|
+
@index = Index.new :server => self
|
37
|
+
|
38
|
+
@log = Logger.new('ustate.log', 4, 134217728)
|
39
|
+
@log.level = Logger::INFO
|
34
40
|
|
35
41
|
setup_signals
|
36
42
|
end
|
37
43
|
|
38
44
|
def aggregator(opts = {})
|
39
45
|
require 'ustate/aggregator'
|
40
|
-
@aggregator ||= UState::Aggregator.new(@index, opts)
|
46
|
+
@aggregator ||= UState::Aggregator.new(@index, opts.merge(server: self))
|
41
47
|
end
|
42
48
|
|
43
49
|
def emailer(opts = {})
|
44
50
|
require 'ustate/emailer'
|
45
|
-
@emailer ||= UState::Emailer.new(@index, opts)
|
51
|
+
@emailer ||= UState::Emailer.new(@index, opts.merge(server: self))
|
46
52
|
end
|
47
53
|
|
48
54
|
def graphite(opts = {})
|
49
55
|
require 'ustate/graphite'
|
50
|
-
@graphite ||= UState::Graphite.new(@index, opts)
|
56
|
+
@graphite ||= UState::Graphite.new(@index, opts.merge(server: self))
|
51
57
|
end
|
52
58
|
|
53
59
|
def start
|
@@ -17,7 +17,7 @@ class UState::Server
|
|
17
17
|
|
18
18
|
# Connect the server
|
19
19
|
def connect
|
20
|
-
|
20
|
+
@server.log.info "Listening on #{@host}:#{@port}"
|
21
21
|
@signature = EventMachine.start_server(@host, @port, Connection, &method(:initialize_connection))
|
22
22
|
end
|
23
23
|
|
data/lib/ustate/server/index.rb
CHANGED
data/lib/ustate/state.rb
CHANGED
@@ -34,11 +34,10 @@ module UState
|
|
34
34
|
init.service ||= mode states.map(&:service)
|
35
35
|
|
36
36
|
# Time
|
37
|
-
init.time
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
rescue
|
37
|
+
init.time = begin
|
38
|
+
times = states.map(&:time).compact
|
39
|
+
(times.inject(:+) / times.size).to_i
|
40
|
+
rescue
|
42
41
|
end
|
43
42
|
init.time ||= Time.now.to_i
|
44
43
|
|
@@ -69,10 +68,9 @@ module UState
|
|
69
68
|
init.service ||= mode states.map(&:service)
|
70
69
|
|
71
70
|
# Time
|
72
|
-
init.time
|
73
|
-
|
74
|
-
|
75
|
-
end / states.size).to_i
|
71
|
+
init.time = begin
|
72
|
+
times = states.map(&:time).compact
|
73
|
+
(times.inject(:+) / times.size).to_i
|
76
74
|
rescue
|
77
75
|
end
|
78
76
|
init.time ||= Time.now.to_i
|
@@ -104,11 +102,10 @@ module UState
|
|
104
102
|
end
|
105
103
|
|
106
104
|
# Time
|
107
|
-
init.time
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
rescue
|
105
|
+
init.time = begin
|
106
|
+
times = states.map(&:time).compact
|
107
|
+
(times.inject(:+) / times.size).to_i
|
108
|
+
rescue
|
112
109
|
end
|
113
110
|
init.time ||= Time.now.to_i
|
114
111
|
|
@@ -145,6 +142,12 @@ module UState
|
|
145
142
|
end
|
146
143
|
end
|
147
144
|
|
145
|
+
def initialize(*a)
|
146
|
+
super *a
|
147
|
+
|
148
|
+
@time ||= Time.now.to_i
|
149
|
+
end
|
150
|
+
|
148
151
|
def metric
|
149
152
|
@metric || metric_f
|
150
153
|
end
|
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.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-17 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: beefcake
|
16
|
-
requirement: &
|
16
|
+
requirement: &73107330 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.3.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *73107330
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: trollop
|
27
|
-
requirement: &
|
27
|
+
requirement: &73106920 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.16.2
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *73106920
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: mtrc
|
38
|
-
requirement: &
|
38
|
+
requirement: &73106530 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 0.0.4
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *73106530
|
47
47
|
description:
|
48
48
|
email: aphyr@aphyr.com
|
49
49
|
executables: []
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- lib/ustate/graphite.rb
|
55
55
|
- lib/ustate/query_string.treetop
|
56
56
|
- lib/ustate/message.rb
|
57
|
+
- lib/ustate/auto_state.rb
|
57
58
|
- lib/ustate/metric_thread.rb
|
58
59
|
- lib/ustate/aggregator.rb
|
59
60
|
- lib/ustate/version.rb
|