right_agent 0.6.6 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/lib/right_agent/agent.rb +26 -25
  2. data/lib/right_agent/agent_config.rb +28 -2
  3. data/lib/right_agent/command/command_constants.rb +2 -2
  4. data/lib/right_agent/core_payload_types/executable_bundle.rb +3 -21
  5. data/lib/right_agent/core_payload_types/login_user.rb +19 -4
  6. data/lib/right_agent/core_payload_types/recipe_instantiation.rb +7 -1
  7. data/lib/right_agent/core_payload_types/right_script_instantiation.rb +7 -1
  8. data/lib/right_agent/dispatcher.rb +6 -19
  9. data/lib/right_agent/idempotent_request.rb +72 -17
  10. data/lib/right_agent/monkey_patches/ruby_patch.rb +0 -1
  11. data/lib/right_agent/monkey_patches.rb +0 -1
  12. data/lib/right_agent/operation_result.rb +27 -4
  13. data/lib/right_agent/packets.rb +47 -23
  14. data/lib/right_agent/platform/darwin.rb +33 -2
  15. data/lib/right_agent/platform/linux.rb +98 -2
  16. data/lib/right_agent/platform/windows.rb +41 -6
  17. data/lib/right_agent/platform.rb +11 -2
  18. data/lib/right_agent/scripts/agent_controller.rb +2 -1
  19. data/lib/right_agent/scripts/agent_deployer.rb +2 -2
  20. data/lib/right_agent/scripts/stats_manager.rb +7 -3
  21. data/lib/right_agent/sender.rb +45 -28
  22. data/lib/right_agent.rb +2 -5
  23. data/right_agent.gemspec +5 -3
  24. data/spec/agent_config_spec.rb +1 -1
  25. data/spec/agent_spec.rb +26 -20
  26. data/spec/core_payload_types/login_user_spec.rb +7 -3
  27. data/spec/idempotent_request_spec.rb +218 -48
  28. data/spec/operation_result_spec.rb +19 -0
  29. data/spec/packets_spec.rb +42 -1
  30. data/spec/platform/darwin.rb +11 -0
  31. data/spec/platform/linux.rb +23 -0
  32. data/spec/platform/linux_volume_manager_spec.rb +43 -43
  33. data/spec/platform/platform_spec.rb +35 -32
  34. data/spec/platform/windows.rb +11 -0
  35. data/spec/sender_spec.rb +21 -25
  36. metadata +47 -40
  37. data/lib/right_agent/broker_client.rb +0 -686
  38. data/lib/right_agent/ha_broker_client.rb +0 -1327
  39. data/lib/right_agent/monkey_patches/amqp_patch.rb +0 -274
  40. data/lib/right_agent/monkey_patches/ruby_patch/string_patch.rb +0 -107
  41. data/lib/right_agent/stats_helper.rb +0 -745
  42. data/spec/broker_client_spec.rb +0 -962
  43. data/spec/ha_broker_client_spec.rb +0 -1695
  44. data/spec/monkey_patches/amqp_patch_spec.rb +0 -100
  45. data/spec/monkey_patches/string_patch_spec.rb +0 -99
  46. data/spec/stats_helper_spec.rb +0 -686
@@ -1,686 +0,0 @@
1
- #
2
- # Copyright (c) 2009-2011 RightScale Inc
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
-
23
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
24
-
25
- describe RightScale::StatsHelper do
26
-
27
- before(:all) do
28
- @original_recent_size = RightScale::StatsHelper::ActivityStats::RECENT_SIZE
29
- RightScale::StatsHelper::ActivityStats.const_set(:RECENT_SIZE, 10)
30
- end
31
-
32
- after(:all) do
33
- RightScale::StatsHelper::ActivityStats.const_set(:RECENT_SIZE, @original_recent_size)
34
- end
35
-
36
- include FlexMock::ArgumentTypes
37
-
38
- describe "ActivityStats" do
39
-
40
- before(:each) do
41
- @now = 1000000
42
- flexmock(Time).should_receive(:now).and_return(@now).by_default
43
- @stats = RightScale::StatsHelper::ActivityStats.new
44
- end
45
-
46
- it "should initialize stats data" do
47
- @stats.instance_variable_get(:@interval).should == 0.0
48
- @stats.instance_variable_get(:@last_start_time).should == @now
49
- @stats.instance_variable_get(:@avg_duration).should be_nil
50
- @stats.instance_variable_get(:@total).should == 0
51
- @stats.instance_variable_get(:@count_per_type).should == {}
52
- end
53
-
54
- it "should update count and interval information" do
55
- flexmock(Time).should_receive(:now).and_return(1000010)
56
- @stats.update
57
- @stats.instance_variable_get(:@interval).should == 1.0
58
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
59
- @stats.instance_variable_get(:@avg_duration).should be_nil
60
- @stats.instance_variable_get(:@total).should == 1
61
- @stats.instance_variable_get(:@count_per_type).should == {}
62
- end
63
-
64
- it "should update weight the average interval toward recent activity" do
65
- end
66
-
67
- it "should update counts per type when type provided" do
68
- flexmock(Time).should_receive(:now).and_return(1000010)
69
- @stats.update("test")
70
- @stats.instance_variable_get(:@interval).should == 1.0
71
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
72
- @stats.instance_variable_get(:@avg_duration).should be_nil
73
- @stats.instance_variable_get(:@total).should == 1
74
- @stats.instance_variable_get(:@count_per_type).should == {"test" => 1}
75
- end
76
-
77
- it "should not update counts when type contains 'stats'" do
78
- flexmock(Time).should_receive(:now).and_return(1000010)
79
- @stats.update("my stats")
80
- @stats.instance_variable_get(:@interval).should == 0.0
81
- @stats.instance_variable_get(:@last_start_time).should == @now
82
- @stats.instance_variable_get(:@avg_duration).should be_nil
83
- @stats.instance_variable_get(:@total).should == 0
84
- @stats.instance_variable_get(:@count_per_type).should == {}
85
- end
86
-
87
- it "should limit length of type string when submitting update" do
88
- flexmock(Time).should_receive(:now).and_return(1000010)
89
- @stats.update("test 12345678901234567890123456789012345678901234567890123456789")
90
- @stats.instance_variable_get(:@total).should == 1
91
- @stats.instance_variable_get(:@count_per_type).should ==
92
- {"test 1234567890123456789012345678901234567890123456789012..." => 1}
93
- end
94
-
95
- it "should not convert symbol or boolean to string when submitting update" do
96
- flexmock(Time).should_receive(:now).and_return(1000010)
97
- @stats.update(:test)
98
- @stats.update(true)
99
- @stats.update(false)
100
- @stats.instance_variable_get(:@total).should == 3
101
- @stats.instance_variable_get(:@count_per_type).should == {:test => 1, true => 1, false => 1}
102
- end
103
-
104
- it "should convert arbitrary type value to limited-length string when submitting update" do
105
- flexmock(Time).should_receive(:now).and_return(1000010)
106
- @stats.update({1 => 11, 2 => 22})
107
- @stats.update({1 => 11, 2 => 22, 3 => 12345678901234567890123456789012345678901234567890123456789})
108
- @stats.instance_variable_get(:@total).should == 2
109
- @stats.instance_variable_get(:@count_per_type).should == {"{1=>11, 2=>22}" => 1,
110
- "{1=>11, 2=>22, 3=>123456789012345678901234567890123456789..." => 1}
111
- end
112
-
113
- it "should not measure rate if disabled" do
114
- @stats = RightScale::StatsHelper::ActivityStats.new(false)
115
- flexmock(Time).should_receive(:now).and_return(1000010)
116
- @stats.update
117
- @stats.instance_variable_get(:@interval).should == 0.0
118
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
119
- @stats.instance_variable_get(:@avg_duration).should be_nil
120
- @stats.instance_variable_get(:@total).should == 1
121
- @stats.instance_variable_get(:@count_per_type).should == {}
122
- @stats.all.should == {"last" => {"elapsed"=>0}, "total" => 1}
123
- end
124
-
125
- it "should update duration when finish using internal start time by default" do
126
- flexmock(Time).should_receive(:now).and_return(1000010)
127
- @stats.finish
128
- @stats.instance_variable_get(:@interval).should == 0.0
129
- @stats.instance_variable_get(:@last_start_time).should == @now
130
- @stats.instance_variable_get(:@avg_duration).should == 1.0
131
- @stats.instance_variable_get(:@total).should == 0
132
- @stats.instance_variable_get(:@count_per_type).should == {}
133
- end
134
-
135
- it "should update duration when finish using specified start time" do
136
- flexmock(Time).should_receive(:now).and_return(1000030)
137
- @stats.avg_duration.should be_nil
138
- @stats.finish(1000010)
139
- @stats.instance_variable_get(:@interval).should == 0.0
140
- @stats.instance_variable_get(:@last_start_time).should == @now
141
- @stats.instance_variable_get(:@avg_duration).should == 2.0
142
- @stats.instance_variable_get(:@total).should == 0
143
- @stats.instance_variable_get(:@count_per_type).should == {}
144
- end
145
-
146
- it "should convert interval to rate" do
147
- flexmock(Time).should_receive(:now).and_return(1000020)
148
- @stats.avg_rate.should be_nil
149
- @stats.update
150
- @stats.instance_variable_get(:@interval).should == 2.0
151
- @stats.avg_rate.should == 0.5
152
- end
153
-
154
- it "should report number of seconds since last update or nil if no updates" do
155
- flexmock(Time).should_receive(:now).and_return(1000010)
156
- @stats.last.should be_nil
157
- @stats.update
158
- @stats.last.should == {"elapsed" => 0}
159
- end
160
-
161
- it "should report number of seconds since last update and last type" do
162
- @stats.update("test")
163
- flexmock(Time).should_receive(:now).and_return(1000010)
164
- @stats.last.should == {"elapsed" => 10, "type" => "test"}
165
- end
166
-
167
- it "should report whether last activity is still active" do
168
- @stats.update("test", "token")
169
- flexmock(Time).should_receive(:now).and_return(1000010)
170
- @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => true}
171
- @stats.finish(@now - 10, "token")
172
- @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => false}
173
- @stats.instance_variable_get(:@avg_duration).should == 2.0
174
- end
175
-
176
- it "should convert count per type to percentages" do
177
- flexmock(Time).should_receive(:now).and_return(1000010)
178
- @stats.update("foo")
179
- @stats.instance_variable_get(:@total).should == 1
180
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1}
181
- @stats.percentage.should == {"total" => 1, "percent" => {"foo" => 100.0}}
182
- @stats.update("bar")
183
- @stats.instance_variable_get(:@total).should == 2
184
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1, "bar" => 1}
185
- @stats.percentage.should == {"total" => 2, "percent" => {"foo" => 50.0, "bar" => 50.0}}
186
- @stats.update("foo")
187
- @stats.update("foo")
188
- @stats.instance_variable_get(:@total).should == 4
189
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 3, "bar" => 1}
190
- @stats.percentage.should == {"total" => 4, "percent" => {"foo" => 75.0, "bar" => 25.0}}
191
- end
192
-
193
- end # ActivityStats
194
-
195
- describe "ExceptionStats" do
196
-
197
- before(:each) do
198
- @now = 1000000
199
- flexmock(Time).should_receive(:now).and_return(@now).by_default
200
- @stats = RightScale::StatsHelper::ExceptionStats.new
201
- @exception = Exception.new("Test error")
202
- end
203
-
204
- it "should initialize stats data" do
205
- @stats.stats.should be_nil
206
- @stats.instance_variable_get(:@callback).should be_nil
207
- end
208
-
209
- it "should track submitted exception information by category" do
210
- @stats.track("testing", @exception)
211
- @stats.stats.should == {"testing" => {"total" => 1,
212
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
213
- "when" => @now, "where" => nil}]}}
214
- end
215
-
216
- it "should recognize and count repeated exceptions" do
217
- @stats.track("testing", @exception)
218
- @stats.stats.should == {"testing" => {"total" => 1,
219
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
220
- "when" => @now, "where" => nil}]}}
221
- flexmock(Time).should_receive(:now).and_return(1000010)
222
- category = "another"
223
- backtrace = ["here", "and", "there"]
224
- 4.times do |i|
225
- begin
226
- raise ArgumentError, "badarg"
227
- rescue Exception => e
228
- flexmock(e).should_receive(:backtrace).and_return(backtrace)
229
- @stats.track(category, e)
230
- backtrace.shift(2) if i == 1
231
- category = "testing" if i == 2
232
- end
233
- end
234
- @stats.stats.should == {"testing" => {"total" => 2,
235
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
236
- "when" => @now, "where" => nil},
237
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
238
- "when" => @now + 10, "where" => "there"}]},
239
- "another" => {"total" => 3,
240
- "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
241
- "when" => @now + 10, "where" => "here"},
242
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
243
- "when" => @now + 10, "where" => "there"}]}}
244
- end
245
-
246
- it "should limit the number of exceptions stored by eliminating older exceptions" do
247
- (RightScale::StatsHelper::ExceptionStats::MAX_RECENT_EXCEPTIONS + 1).times do |i|
248
- begin
249
- raise ArgumentError, "badarg"
250
- rescue Exception => e
251
- flexmock(e).should_receive(:backtrace).and_return([i.to_s])
252
- @stats.track("testing", e)
253
- end
254
- end
255
- stats = @stats.stats
256
- stats["testing"]["total"].should == RightScale::StatsHelper::ExceptionStats::MAX_RECENT_EXCEPTIONS + 1
257
- stats["testing"]["recent"].size.should == RightScale::StatsHelper::ExceptionStats::MAX_RECENT_EXCEPTIONS
258
- stats["testing"]["recent"][0]["where"].should == "1"
259
- end
260
-
261
- it "should make callback if callback and message defined" do
262
- called = 0
263
- callback = lambda do |exception, message, server|
264
- called += 1
265
- exception.should == @exception
266
- message.should == "message"
267
- server.should == "server"
268
- end
269
- @stats = RightScale::StatsHelper::ExceptionStats.new("server", callback)
270
- @stats.track("testing", @exception, "message")
271
- @stats.stats.should == {"testing" => {"total" => 1,
272
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
273
- "when" => @now, "where" => nil}]}}
274
- called.should == 1
275
- end
276
-
277
- it "should catch any exceptions raised internally" do
278
- flexmock(RightScale::Log).should_receive(:error).with(/Failed to track exception/).once
279
- flexmock(@exception).should_receive(:backtrace).and_raise(Exception)
280
- @stats = RightScale::StatsHelper::ExceptionStats.new
281
- @stats.track("testing", @exception, "message")
282
- @stats.stats["testing"]["total"].should == 1
283
- end
284
-
285
- end # ExceptionStats
286
-
287
- describe "Formatting" do
288
-
289
- include RightScale::StatsHelper
290
-
291
- before(:each) do
292
- @now = 1000000
293
- flexmock(Time).should_receive(:now).and_return(@now).by_default
294
- @exceptions = RightScale::StatsHelper::ExceptionStats.new
295
- @brokers = {"brokers"=> [{"alias" => "b0", "identity" => "rs-broker-localhost-5672", "status" => "connected",
296
- "disconnect last" => nil,"disconnects" => nil, "failure last" => nil, "failures" => nil,
297
- "retries" => nil},
298
- {"alias" => "b1", "identity" => "rs-broker-localhost-5673", "status" => "disconnected",
299
- "disconnect last" => {"elapsed" => 1000}, "disconnects" => 2,
300
- "failure last" => nil, "failures" => nil, "retries" => nil},
301
- {"alias" => "b2", "identity" => "rs-broker-localhost-5674", "status" => "failed",
302
- "disconnect last" => nil, "disconnects" => nil,
303
- "failure last" => {"elapsed" => 1000}, "failures" => 3, "retries" => 2}],
304
- "heartbeat" => nil,
305
- "exceptions" => {}}
306
- end
307
-
308
- it "should convert values to percentages" do
309
- stats = {"first" => 1, "second" => 4, "third" => 3}
310
- result = percentage(stats)
311
- result.should == {"total" => 8, "percent" => {"first" => 12.5, "second" => 50.0, "third" => 37.5}}
312
- end
313
-
314
- it "should convert 0 to nil" do
315
- nil_if_zero(0).should be_nil
316
- nil_if_zero(0.0).should be_nil
317
- nil_if_zero(1).should == 1
318
- nil_if_zero(1.0).should == 1.0
319
- end
320
-
321
- it "should sort hash by key into array with integer conversion of keys if possible" do
322
- sort_key({"c" => 3, "a" => 1, "b" => 2}).should == [["a", 1], ["b", 2], ["c", 3]]
323
- sort_key({3 => "c", 1 => "a", 2 => "b"}).should == [[1, "a"], [2, "b"], [3, "c"]]
324
- sort_key({11 => "c", 9 => "a", 10 => "b"}).should == [[9, "a"], [10, "b"], [11, "c"]]
325
- sort_key({"append_info" => 9.6, "create_new_section" => 8.5, "append_output" => 7.3, "record" => 4.7,
326
- "update_status" => 4.4,
327
- "declare" => 39.2, "list_agents" => 3.7, "update_tags" => 3.2, "append_error" => 3.0,
328
- "add_user" => 2.4, "get_boot_bundle" => 1.4, "get_repositories" => 1.4,
329
- "update_login_policy" => 1.3, "schedule_decommission" => 0.91, "update_inputs" => 0.75,
330
- "delete_queues" => 0.75, "soft_decommission" => 0.75, "remove" => 0.66,
331
- "get_login_policy" => 0.58, "ping" => 0.50, "update_entry" => 0.25, "query_tags" => 0.083,
332
- "get_decommission_bundle" => 0.083, "list_queues" => 0.083}).should ==
333
- [["add_user", 2.4], ["append_error", 3.0], ["append_info", 9.6], ["append_output", 7.3],
334
- ["create_new_section", 8.5], ["declare", 39.2], ["delete_queues", 0.75], ["get_boot_bundle", 1.4],
335
- ["get_decommission_bundle", 0.083], ["get_login_policy", 0.58], ["get_repositories", 1.4],
336
- ["list_agents", 3.7], ["list_queues", 0.083], ["ping", 0.5], ["query_tags", 0.083],
337
- ["record", 4.7], ["remove", 0.66], ["schedule_decommission", 0.91], ["soft_decommission", 0.75],
338
- ["update_entry", 0.25], ["update_inputs", 0.75],
339
- ["update_login_policy", 1.3], ["update_status", 4.4], ["update_tags", 3.2]]
340
- end
341
-
342
- it "should sort hash by value into array" do
343
- sort_value({"c" => 3, "a" => 2, "b" => 1}).should == [["b", 1], ["a", 2], ["c", 3]]
344
- sort_value({"c" => 3.0, "a" => 2, "b" => 1.0}).should == [["b", 1.0], ["a", 2], ["c", 3.0]]
345
- sort_value({"append_info" => 9.6, "create_new_section" => 8.5, "append_output" => 7.3, "record" => 4.7,
346
- "update_status" => 4.4,
347
- "declare" => 39.2, "list_agents" => 3.7, "update_tags" => 3.2, "append_error" => 3.0,
348
- "add_user" => 2.4, "get_boot_bundle" => 1.4, "get_repositories" => 1.4,
349
- "update_login_policy" => 1.3, "schedule_decommission" => 0.91, "update_inputs" => 0.75,
350
- "delete_queues" => 0.75, "soft_decommission" => 0.75, "remove" => 0.66,
351
- "get_login_policy" => 0.58, "ping" => 0.50, "update_entry" => 0.25, "query_tags" => 0.083,
352
- "get_decommission_bundle" => 0.083, "list_queues" => 0.083}).should ==
353
- [["list_queues", 0.083], ["query_tags", 0.083], ["get_decommission_bundle", 0.083],
354
- ["update_entry", 0.25], ["ping", 0.5], ["get_login_policy", 0.58], ["remove", 0.66],
355
- ["delete_queues", 0.75], ["soft_decommission", 0.75], ["update_inputs", 0.75],
356
- ["schedule_decommission", 0.91], ["update_login_policy", 1.3], ["get_repositories", 1.4],
357
- ["get_boot_bundle", 1.4], ["add_user", 2.4], ["append_error", 3.0], ["update_tags", 3.2],
358
- ["list_agents", 3.7], ["update_status", 4.4],
359
- ["record", 4.7], ["append_output", 7.3], ["create_new_section", 8.5], ["append_info", 9.6],
360
- ["declare", 39.2]]
361
- end
362
-
363
- it "should wrap string by breaking it into lines at the specified separator" do
364
- string = "Now is the time for all good men to come to the aid of their people."
365
- result = wrap(string, 20, " ", " ")
366
- result.should == "Now is the time for \n" +
367
- " all good men to come \n" +
368
- " to the aid of their \n" +
369
- " people."
370
- string = "dogs: 2, cats: 10, hippopotami: 99, bears: 1, ants: 100000"
371
- result = wrap(string, 22, "--", ", ")
372
- result.should == "dogs: 2, cats: 10, \n" +
373
- "--hippopotami: 99, \n" +
374
- "--bears: 1, ants: 100000"
375
- end
376
-
377
- it "should convert elapsed time to displayable format" do
378
- elapsed(0).should == "0 sec"
379
- elapsed(1).should == "1 sec"
380
- elapsed(60).should == "60 sec"
381
- elapsed(61).should == "1 min 1 sec"
382
- elapsed(62).should == "1 min 2 sec"
383
- elapsed(120).should == "2 min 0 sec"
384
- elapsed(3600).should == "60 min 0 sec"
385
- elapsed(3601).should == "1 hr 0 min"
386
- elapsed(3659).should == "1 hr 0 min"
387
- elapsed(3660).should == "1 hr 1 min"
388
- elapsed(3720).should == "1 hr 2 min"
389
- elapsed(7200).should == "2 hr 0 min"
390
- elapsed(7260).should == "2 hr 1 min"
391
- elapsed(86400).should == "24 hr 0 min"
392
- elapsed(86401).should == "1 day 0 hr 0 min"
393
- elapsed(86459).should == "1 day 0 hr 0 min"
394
- elapsed(86460).should == "1 day 0 hr 1 min"
395
- elapsed(90000).should == "1 day 1 hr 0 min"
396
- elapsed(183546).should == "2 days 2 hr 59 min"
397
- elapsed(125.5).should == "2 min 5 sec"
398
- end
399
-
400
- it "should convert floating point values to decimal digit string with at least two digit precision" do
401
- enough_precision(100.5).should == "101"
402
- enough_precision(100.4).should == "100"
403
- enough_precision(99.0).should == "99"
404
- enough_precision(10.5).should == "11"
405
- enough_precision(10.4).should == "10"
406
- enough_precision(9.15).should == "9.2"
407
- enough_precision(9.1).should == "9.1"
408
- enough_precision(1.05).should == "1.1"
409
- enough_precision(1.01).should == "1.0"
410
- enough_precision(1.0).should == "1.0"
411
- enough_precision(0.995).should == "1.00"
412
- enough_precision(0.991).should == "0.99"
413
- enough_precision(0.0995).should == "0.100"
414
- enough_precision(0.0991).should == "0.099"
415
- enough_precision(0.00995).should == "0.0100"
416
- enough_precision(0.00991).should == "0.0099"
417
- enough_precision(0.000995).should == "0.00100"
418
- enough_precision(0.000991).should == "0.00099"
419
- enough_precision(0.000005).should == "0.00001"
420
- enough_precision(0.000001).should == "0.00000"
421
- enough_precision(0.0).should == "0"
422
- enough_precision(55).should == "55"
423
- enough_precision({"a" => 65.0, "b" => 23.0, "c" => 12.0}).should == {"a" => "65", "b" => "23", "c" => "12"}
424
- enough_precision({"a" => 65.0, "b" => 33.0, "c" => 2.0}).should == {"a" => "65.0", "b" => "33.0", "c" => "2.0"}
425
- enough_precision({"a" => 10.45, "b" => 1.0, "c" => 0.011}).should == {"a" => "10.5", "b" => "1.0", "c" => "0.011"}
426
- enough_precision({"a" => 1000.0, "b" => 0.1, "c" => 0.0, "d" => 0.0001, "e" => 0.00001, "f" => 0.000001}).should ==
427
- {"a" => "1000.0", "b" => "0.10", "c" => "0.0", "d" => "0.00010", "e" => "0.00001", "f" => "0.00000"}
428
- enough_precision([["a", 65.0], ["b", 23.0], ["c", 12.0]]).should == [["a", "65"], ["b", "23"], ["c", "12"]]
429
- enough_precision([["a", 65.0], ["b", 33.0], ["c", 2.0]]).should == [["a", "65.0"], ["b", "33.0"], ["c", "2.0"]]
430
- enough_precision([["a", 10.45], ["b", 1.0], ["c", 0.011]]).should == [["a", "10.5"], ["b", "1.0"], ["c", "0.011"]]
431
- enough_precision([["a", 1000.0], ["b", 0.1], ["c", 0.0], ["d", 0.0001], ["e", 0.00001], ["f", 0.000001]]).should ==
432
- [["a", "1000.0"], ["b", "0.10"], ["c", "0.0"], ["d", "0.00010"], ["e", "0.00001"], ["f", "0.00000"]]
433
- end
434
-
435
- it "should convert broker status to multi-line display string" do
436
- result = brokers_str(@brokers, 10)
437
- result.should == "brokers : b0: rs-broker-localhost-5672 connected, disconnects: none, failures: none\n" +
438
- " b1: rs-broker-localhost-5673 disconnected, disconnects: 2 (16 min 40 sec ago), failures: none\n" +
439
- " b2: rs-broker-localhost-5674 failed, disconnects: none, failures: 3 (16 min 40 sec ago w/ 2 retries)\n" +
440
- " exceptions : none\n" +
441
- " heartbeat : none\n" +
442
- " returns : none\n"
443
- end
444
-
445
- it "should display broker exceptions and returns" do
446
- @exceptions.track("testing", Exception.new("Test error"))
447
- @brokers["exceptions"] = @exceptions.stats
448
- @brokers["heartbeat"] = 60
449
- activity = RightScale::StatsHelper::ActivityStats.new
450
- activity.update("no queue")
451
- activity.finish(@now - 10)
452
- activity.update("no queue consumers")
453
- activity.update("no queue consumers")
454
- flexmock(Time).should_receive(:now).and_return(1000010)
455
- @brokers["returns"] = activity.all
456
- result = brokers_str(@brokers, 10)
457
- result.should == "brokers : b0: rs-broker-localhost-5672 connected, disconnects: none, failures: none\n" +
458
- " b1: rs-broker-localhost-5673 disconnected, disconnects: 2 (16 min 40 sec ago), failures: none\n" +
459
- " b2: rs-broker-localhost-5674 failed, disconnects: none, failures: 3 (16 min 40 sec ago w/ 2 retries)\n" +
460
- " exceptions : testing total: 1, most recent:\n" +
461
- " (1) Mon Jan 12 05:46:40 Exception: Test error\n" +
462
- " \n" +
463
- " heartbeat : 60 sec\n" +
464
- " returns : no queue consumers: 67%, no queue: 33%, total: 3, \n" +
465
- " last: no queue consumers (10 sec ago), rate: 0/sec\n"
466
- end
467
-
468
- it 'should convert activity stats to string' do
469
- activity = RightScale::StatsHelper::ActivityStats.new
470
- activity.update("testing")
471
- activity.finish(@now - 10)
472
- activity.update("more testing")
473
- activity.update("more testing")
474
- activity.update("more testing")
475
- flexmock(Time).should_receive(:now).and_return(1000010)
476
- activity_str(activity.all).should == "more testing: 75%, testing: 25%, total: 4, last: more testing (10 sec ago), " +
477
- "rate: 0/sec"
478
- end
479
-
480
- it 'should convert last activity stats to string' do
481
- activity = RightScale::StatsHelper::ActivityStats.new
482
- activity.update("testing")
483
- activity.finish(@now - 10)
484
- activity.update("more testing")
485
- flexmock(Time).should_receive(:now).and_return(1000010)
486
- last_activity_str(activity.last).should == "more testing: 10 sec ago"
487
- last_activity_str(activity.last, single_item = true).should == "more testing (10 sec ago)"
488
- end
489
-
490
- it "should convert exception stats to multi-line string" do
491
- @exceptions.track("testing", Exception.new("This is a very long exception message that should be truncated " +
492
- "to a reasonable length"))
493
- flexmock(Time).should_receive(:now).and_return(1000010)
494
- category = "another"
495
- backtrace = ["It happened here", "Over there"]
496
- 4.times do |i|
497
- begin
498
- raise ArgumentError, "badarg"
499
- rescue Exception => e
500
- flexmock(e).should_receive(:backtrace).and_return(backtrace)
501
- @exceptions.track(category, e)
502
- backtrace.shift(1) if i == 1
503
- category = "testing" if i == 2
504
- end
505
- end
506
-
507
- result = exceptions_str(@exceptions.stats, "----")
508
- result.should == "another total: 3, most recent:\n" +
509
- "----(1) Mon Jan 12 05:46:50 ArgumentError: badarg\n" +
510
- "---- Over there\n" +
511
- "----(2) Mon Jan 12 05:46:50 ArgumentError: badarg\n" +
512
- "---- It happened here\n" +
513
- "----testing total: 2, most recent:\n" +
514
- "----(1) Mon Jan 12 05:46:50 ArgumentError: badarg\n" +
515
- "---- Over there\n" +
516
- "----(1) Mon Jan 12 05:46:40 Exception: This is a very long exception message that should be trun...\n" +
517
- "---- "
518
- end
519
-
520
- it "should convert nested hash into string with keys sorted numerically if possible, else alphabetically" do
521
- hash = {"dogs" => 2, "cats" => 3, "hippopotami" => 99, "bears" => 1, "ants" => 100000000, "dragons" => nil,
522
- "food" => {"apples" => "bushels", "berries" => "lots", "meat" => {"fish" => 10.54, "beef" => nil}},
523
- "versions" => { "1" => 10, "5" => 50, "10" => 100} }
524
- result = hash_str(hash)
525
- result.should == "ants: 100000000, bears: 1, cats: 3, dogs: 2, dragons: none, " +
526
- "food: [ apples: bushels, berries: lots, meat: [ beef: none, fish: 11 ] ], " +
527
- "hippopotami: 99, versions: [ 1: 10, 5: 50, 10: 100 ]"
528
- result = wrap(result, 20, "----", ", ")
529
- result.should == "ants: 100000000, \n" +
530
- "----bears: 1, cats: 3, \n" +
531
- "----dogs: 2, \n" +
532
- "----dragons: none, \n" +
533
- "----food: [ apples: bushels, \n" +
534
- "----berries: lots, \n" +
535
- "----meat: [ beef: none, \n" +
536
- "----fish: 11 ] ], \n" +
537
- "----hippopotami: 99, \n" +
538
- "----versions: [ 1: 10, \n" +
539
- "----5: 50, 10: 100 ]"
540
- end
541
-
542
- it "should convert sub-stats to a display string" do
543
- @exceptions.track("testing", Exception.new("Test error"))
544
- activity1 = RightScale::StatsHelper::ActivityStats.new
545
- activity2 = RightScale::StatsHelper::ActivityStats.new
546
- activity3 = RightScale::StatsHelper::ActivityStats.new
547
- activity2.update("stats")
548
- activity2.update("testing")
549
- activity2.update("more testing")
550
- activity2.update("more testing")
551
- activity2.update("more testing")
552
- activity3.update("testing forever", "id")
553
- flexmock(Time).should_receive(:now).and_return(1002800)
554
-
555
- stats = {"exceptions" => @exceptions.stats,
556
- "empty_hash" => {},
557
- "float_value" => 3.15,
558
- "some % percent" => 3.54,
559
- "some time" => 0.675,
560
- "some rate" => 4.72,
561
- "some age" => 125,
562
- "activity1 %" => activity1.percentage,
563
- "activity1 last" => activity1.last,
564
- "activity2 %" => activity2.percentage,
565
- "activity2 last" => activity2.last,
566
- "activity3 last" => activity3.last,
567
- "some hash" => {"dogs" => 2, "cats" => 3, "hippopotami" => 99, "bears" => 1,
568
- "ants" => 100000000, "dragons" => nil, "leopards" => 25}}
569
-
570
- result = sub_stats_str("my sub-stats", stats, 13)
571
- result.should == "my sub-stats : activity1 % : none\n" +
572
- " activity1 last : none\n" +
573
- " activity2 % : more testing: 75%, testing: 25%, total: 4\n" +
574
- " activity2 last : more testing: 46 min 40 sec ago\n" +
575
- " activity3 last : testing forever: 46 min 40 sec ago and still active\n" +
576
- " empty_hash : none\n" +
577
- " exceptions : testing total: 1, most recent:\n" +
578
- " (1) Mon Jan 12 05:46:40 Exception: Test error\n" +
579
- " \n" +
580
- " float_value : 3.2\n" +
581
- " some % : 3.5%\n" +
582
- " some age : 2 min 5 sec\n" +
583
- " some hash : ants: 100000000, bears: 1, cats: 3, dogs: 2, dragons: none, hippopotami: 99, \n" +
584
- " leopards: 25\n" +
585
- " some rate : 4.7/sec\n" +
586
- " some time : 0.68 sec\n"
587
- end
588
-
589
- it "should convert stats to a display string with special formatting for generic keys" do
590
- @exceptions.track("testing", Exception.new("Test error"))
591
- activity = RightScale::StatsHelper::ActivityStats.new
592
- activity.update("testing")
593
- flexmock(Time).should_receive(:now).and_return(1000010)
594
- sub_stats = {"exceptions" => @exceptions.stats,
595
- "empty_hash" => {},
596
- "float_value" => 3.15,
597
- "activity %" => activity.percentage,
598
- "activity last" => activity.last,
599
- "some hash" => {"dogs" => 2, "cats" => 3, "hippopotami" => 99, "bears" => 1,
600
- "ants" => 100000000, "dragons" => nil, "leopards" => 25}}
601
- stats = {"stat time" => @now,
602
- "last reset time" => @now,
603
- "service uptime" => 3720,
604
- "machine uptime" => 183546,
605
- "version" => 10,
606
- "brokers" => @brokers,
607
- "hostname" => "localhost",
608
- "identity" => "unit tester",
609
- "stuff stats" => sub_stats}
610
-
611
- result = stats_str(stats)
612
- result.should == "identity : unit tester\n" +
613
- "hostname : localhost\n" +
614
- "stat time : Mon Jan 12 05:46:40\n" +
615
- "last reset : Mon Jan 12 05:46:40\n" +
616
- "service up : 1 hr 2 min\n" +
617
- "machine up : 2 days 2 hr 59 min\n" +
618
- "version : 10\n" +
619
- "brokers : b0: rs-broker-localhost-5672 connected, disconnects: none, failures: none\n" +
620
- " b1: rs-broker-localhost-5673 disconnected, disconnects: 2 (16 min 40 sec ago), failures: none\n" +
621
- " b2: rs-broker-localhost-5674 failed, disconnects: none, failures: 3 (16 min 40 sec ago w/ 2 retries)\n" +
622
- " exceptions : none\n" +
623
- " heartbeat : none\n" +
624
- " returns : none\n" +
625
- "stuff : activity % : testing: 100%, total: 1\n" +
626
- " activity last : testing: 10 sec ago\n" +
627
- " empty_hash : none\n" +
628
- " exceptions : testing total: 1, most recent:\n" +
629
- " (1) Mon Jan 12 05:46:40 Exception: Test error\n" +
630
- " \n" +
631
- " float_value : 3.2\n" +
632
- " some hash : ants: 100000000, bears: 1, cats: 3, dogs: 2, dragons: none, hippopotami: 99, \n" +
633
- " leopards: 25\n"
634
- end
635
-
636
- it "should treat broker status, version, and machine uptime as optional" do
637
- sub_stats = {"exceptions" => @exceptions.stats,
638
- "empty_hash" => {},
639
- "float_value" => 3.15}
640
-
641
- stats = {"stat time" => @now,
642
- "last reset time" => @now,
643
- "service uptime" => 1000,
644
- "hostname" => "localhost",
645
- "identity" => "unit tester",
646
- "stuff stats" => sub_stats}
647
-
648
- result = stats_str(stats)
649
- result.should == "identity : unit tester\n" +
650
- "hostname : localhost\n" +
651
- "stat time : Mon Jan 12 05:46:40\n" +
652
- "last reset : Mon Jan 12 05:46:40\n" +
653
- "service up : 16 min 40 sec\n" +
654
- "stuff : empty_hash : none\n" +
655
- " exceptions : none\n" +
656
- " float_value : 3.2\n"
657
- end
658
-
659
- it "should display name if provided" do
660
- sub_stats = {"exceptions" => @exceptions.stats,
661
- "empty_hash" => {},
662
- "float_value" => 3.15}
663
-
664
- stats = {"stat time" => @now,
665
- "last reset time" => @now,
666
- "service uptime" => 1000,
667
- "hostname" => "localhost",
668
- "identity" => "unit tester",
669
- "name" => "tester_1",
670
- "stuff stats" => sub_stats}
671
-
672
- result = stats_str(stats)
673
- result.should == "name : tester_1\n" +
674
- "identity : unit tester\n" +
675
- "hostname : localhost\n" +
676
- "stat time : Mon Jan 12 05:46:40\n" +
677
- "last reset : Mon Jan 12 05:46:40\n" +
678
- "service up : 16 min 40 sec\n" +
679
- "stuff : empty_hash : none\n" +
680
- " exceptions : none\n" +
681
- " float_value : 3.2\n"
682
- end
683
-
684
- end # Formatting
685
-
686
- end # RightScale::StatsHelper