cloudpi-appmetric 0.1.0 → 0.2.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/VERSION +1 -1
- data/lib/cloudpi-appmetric.rb +115 -134
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/cloudpi-appmetric.rb
CHANGED
@@ -1,177 +1,158 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'json'
|
3
|
+
require 'thread'
|
3
4
|
|
4
5
|
module CloudPI
|
5
6
|
|
6
7
|
class AppMetric
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def first
|
28
|
-
return nil if is_empty
|
29
|
-
@lock.synchronize { return @memory[(@front + 1) % @queue_size] }
|
30
|
-
end
|
31
|
-
|
32
|
-
def pop
|
33
|
-
return if is_empty
|
34
|
-
@lock.synchronize { @front = (@front + 1) % @queue_size }
|
35
|
-
end
|
36
|
-
|
37
|
-
def enqueue(data)
|
38
|
-
if is_full
|
39
|
-
@lock.synchronize {
|
40
|
-
@front = (@front + 1) % @queue_size
|
41
|
-
@rear = (@rear + 1) % @queue_size
|
42
|
-
@memory[@rear] = data
|
43
|
-
}
|
44
|
-
else
|
45
|
-
@lock.synchronize {
|
46
|
-
@rear = (@rear + 1) % @queue_size
|
47
|
-
@memory[@rear] = data
|
48
|
-
}
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def dequeue
|
53
|
-
return nil if is_empty
|
54
|
-
|
55
|
-
@lock.synchronize {
|
56
|
-
@front = (@front + 1) % @queue_size
|
57
|
-
return @memory[@front]
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
|
-
def cursor
|
62
|
-
return "#{@front}:#{@rear}"
|
8
|
+
|
9
|
+
# sleep time in thread loop - checking queue, retrying to connect.
|
10
|
+
SLEEP_TIME = 3.0 # sec
|
11
|
+
|
12
|
+
def initialize(bridge_ip = 'localhost', bridge_port = 5999, policy = '{}')
|
13
|
+
@bridge_ip = bridge_ip
|
14
|
+
@bridge_port = bridge_port
|
15
|
+
@queue = SizedQueue.new(4096)
|
16
|
+
@mutex = Mutex.new
|
17
|
+
|
18
|
+
begin
|
19
|
+
json = JSON.parse(ENV['VCAP_APPLICATION'], {:symbolize_names => true})
|
20
|
+
@app_ip = json[:host]
|
21
|
+
@app_port = json[:port]
|
22
|
+
@app_id = json[:app_id]
|
23
|
+
@instance_id = json[:instance_id]
|
24
|
+
rescue JSON::ParserError, TypeError
|
25
|
+
# parsing error: ENV['VCAP_APPLICATION']
|
26
|
+
# log error "parsing error: ENV['VCAP_APPLICATION']"
|
63
27
|
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def initialize(bridge_ip = 'localhost', bridge_port = 5999, metric_policy = '{}')
|
67
|
-
@app_ip = ENV["VCAP_APP_HOST"] || '127.0.0.1'
|
68
|
-
@app_port = ENV["VCAP_APP_PORT"] || 9999
|
69
|
-
env_vcap_application = JSON.parse(ENV["VCAP_APPLICATION"])
|
70
|
-
app_id = env_vcap_application["app_id"] if env_vcap_application
|
71
|
-
instance_id = env_vcap_application["instance_id"] if env_vcap_application
|
72
|
-
@app_id = app_id || ''
|
73
|
-
@instance_id = instance_id || ''
|
74
|
-
@bridge_ip = bridge_ip
|
75
|
-
@bridge_port = bridge_port
|
76
|
-
@metric_policy = JSON.parse(metric_policy)
|
77
|
-
@queue = CircularQueue.new(4096)
|
78
28
|
|
29
|
+
@policy = parse(metric_policy)
|
30
|
+
@policy_published = false
|
31
|
+
|
32
|
+
# log info "key: @#!$!"
|
79
33
|
connect
|
80
|
-
|
34
|
+
run
|
81
35
|
end
|
82
|
-
|
36
|
+
|
83
37
|
def connect
|
84
38
|
begin
|
85
39
|
@conn = TCPSocket.new(@bridge_ip, @bridge_port)
|
86
|
-
|
87
|
-
|
40
|
+
# log info "connected to bridge"
|
41
|
+
@policy_published = false
|
42
|
+
send_policy
|
88
43
|
rescue
|
89
44
|
# ignore connection error
|
45
|
+
# log error "cann't connect to bridge."
|
90
46
|
nil
|
91
47
|
end
|
92
48
|
end
|
93
|
-
|
49
|
+
|
94
50
|
def close
|
95
51
|
@conn.close if @conn
|
52
|
+
# log info "connection closed"
|
96
53
|
end
|
97
|
-
|
98
|
-
def
|
99
|
-
#
|
100
|
-
# "IP-ADDRESS:PORT:APP-INSTANCE-ID".
|
101
|
-
|
102
|
-
# "#{@app_ip}:#{@app_port}:#{@instance_id}"
|
103
|
-
"#{@app_ip}:#{@app_port}:#{@app_id}:#{@instance_id}"
|
54
|
+
|
55
|
+
def key
|
56
|
+
:"#{@app_ip}:#{@app_port}:#{@app_id}:#{@instance_id}"
|
104
57
|
end
|
105
|
-
|
106
|
-
def
|
107
|
-
|
108
|
-
|
58
|
+
|
59
|
+
def parse(raw)
|
60
|
+
begin
|
61
|
+
json = JSON.parse(raw, {:symbolize_names => true})
|
62
|
+
json = {} unless json.is_a?(Hash)
|
63
|
+
json
|
64
|
+
rescue JSON::ParserError
|
65
|
+
# log error "parse error"
|
66
|
+
{}
|
67
|
+
end
|
109
68
|
end
|
110
|
-
|
111
|
-
def
|
112
|
-
|
69
|
+
|
70
|
+
def circular_enqueue(obj)
|
71
|
+
# enqueue like a circular-queue
|
72
|
+
# store messages into queue then loop thread will push to bridge
|
73
|
+
@mutex.synchronize {
|
74
|
+
begin
|
75
|
+
while @queue.length >= @queue.max do
|
76
|
+
# queue is full.
|
77
|
+
# log info "queue is full."
|
78
|
+
@queue.pop(true)
|
79
|
+
end
|
80
|
+
rescue ThreadError
|
81
|
+
# queue is empty.
|
82
|
+
# log info "queue is empty."
|
83
|
+
end
|
84
|
+
@queue.push(obj)
|
85
|
+
}
|
113
86
|
end
|
114
|
-
|
115
|
-
def
|
116
|
-
|
117
|
-
|
87
|
+
|
88
|
+
def set_policy(policy)
|
89
|
+
@policy = parse(policy)
|
90
|
+
# log info "set_policy: #{@policy.to_json}"
|
118
91
|
end
|
119
|
-
|
92
|
+
|
93
|
+
def add_policy(policy)
|
94
|
+
# TODO
|
95
|
+
end
|
96
|
+
|
97
|
+
def remove_policy(policy)
|
98
|
+
# TODO
|
99
|
+
end
|
100
|
+
|
120
101
|
def send_heartbeat
|
121
|
-
|
102
|
+
# log debug "heartbeat into queue"
|
103
|
+
circular_enqueue({:"#{key}" => {:alive => Time.now.to_i}}.to_json)
|
122
104
|
end
|
123
|
-
|
124
|
-
def
|
125
|
-
#
|
126
|
-
|
127
|
-
|
105
|
+
|
106
|
+
def send_policy
|
107
|
+
# log debug "policy into queue"
|
108
|
+
@policy[:when] = Time.now.to_i
|
109
|
+
circular_enqueue({:"#{key}" => @policy}.to_json)
|
110
|
+
@policy_published = true;
|
111
|
+
end
|
112
|
+
|
113
|
+
def send_metric(metric)
|
114
|
+
# log debug "metric into queue"
|
115
|
+
msg = parse(metric)
|
128
116
|
msg[:when] = Time.now.to_i
|
129
|
-
|
130
|
-
message = {metric_key => msg}.to_json
|
131
|
-
|
132
|
-
@queue.enqueue(message)
|
117
|
+
circular_enqueue({:"#{key}" => msg}.to_json)
|
133
118
|
end
|
119
|
+
|
120
|
+
def set_trap(thread)
|
121
|
+
# Thread exit when signal triggered
|
122
|
+
Signal.trap("TERM") do
|
123
|
+
# log info "TERM signal received."
|
124
|
+
Thread.kill(thread) if thread
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def run
|
129
|
+
# no needs to send heartbeat, dea will do that..
|
134
130
|
|
135
|
-
|
136
|
-
thread = Thread.new do
|
131
|
+
t = Thread.new do
|
137
132
|
loop do
|
138
|
-
|
139
|
-
|
140
|
-
|
133
|
+
|
134
|
+
# log debug "queue capacity: #{@queue.length}/#{@queue.max}"
|
135
|
+
while !@queue.empty? do
|
136
|
+
@msg = @queue.pop unless @msg # @msg stores last failed msg.
|
141
137
|
begin
|
142
|
-
@conn.write("#{@
|
143
|
-
#
|
144
|
-
@
|
138
|
+
@conn.write("#{@msg}\0")
|
139
|
+
# log debug "send msg: #{@msg}"
|
140
|
+
@msg = nil
|
145
141
|
rescue
|
146
142
|
# retry to connect
|
147
|
-
|
143
|
+
# log error "cann't write to bridge."
|
144
|
+
sleep(SLEEP_TIME)
|
148
145
|
connect
|
149
146
|
end
|
150
147
|
end # while
|
151
|
-
sleep(3.0)
|
152
|
-
end # loop
|
153
|
-
end # thread
|
154
|
-
|
155
|
-
# no need to send heartbeat, dea metric will do that..
|
156
|
-
|
157
|
-
# heartbeat_thread = Thread.new do
|
158
|
-
# loop do
|
159
|
-
# send_heartbeat
|
160
|
-
# sleep(10.0)
|
161
|
-
# end # loop
|
162
|
-
# end # thread
|
163
|
-
|
164
|
-
set_trap(thread)
|
165
|
-
# set_trap(heartbeat_thread)
|
166
|
-
end
|
167
148
|
|
168
|
-
|
169
|
-
|
170
|
-
Signal.trap("TERM") do
|
171
|
-
Thread.kill(thread) if thread
|
149
|
+
sleep(SLEEP_TIME) # queue is empty
|
150
|
+
end
|
172
151
|
end
|
152
|
+
|
153
|
+
set_trap(t)
|
173
154
|
end
|
174
|
-
|
155
|
+
|
175
156
|
end
|
176
157
|
|
177
158
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudpi-appmetric
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Junsang Yang
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-06-
|
18
|
+
date: 2012-06-11 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
type: :development
|