fiveruns-dash-ruby 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +68 -0
- data/Rakefile +39 -0
- data/lib/fiveruns/dash.rb +144 -0
- data/lib/fiveruns/dash/configuration.rb +116 -0
- data/lib/fiveruns/dash/exception_recorder.rb +135 -0
- data/lib/fiveruns/dash/host.rb +173 -0
- data/lib/fiveruns/dash/instrument.rb +128 -0
- data/lib/fiveruns/dash/metric.rb +379 -0
- data/lib/fiveruns/dash/recipe.rb +63 -0
- data/lib/fiveruns/dash/reporter.rb +208 -0
- data/lib/fiveruns/dash/scm.rb +126 -0
- data/lib/fiveruns/dash/session.rb +81 -0
- data/lib/fiveruns/dash/store/file.rb +24 -0
- data/lib/fiveruns/dash/store/http.rb +198 -0
- data/lib/fiveruns/dash/threads.rb +24 -0
- data/lib/fiveruns/dash/trace.rb +65 -0
- data/lib/fiveruns/dash/typable.rb +29 -0
- data/lib/fiveruns/dash/update.rb +215 -0
- data/lib/fiveruns/dash/version.rb +86 -0
- data/recipes/jruby.rb +107 -0
- data/recipes/ruby.rb +34 -0
- data/test/collector_communication_test.rb +260 -0
- data/test/configuration_test.rb +97 -0
- data/test/exception_recorder_test.rb +112 -0
- data/test/file_store_test.rb +56 -0
- data/test/fixtures/http_store_test/response.json +6 -0
- data/test/http_store_test.rb +210 -0
- data/test/metric_test.rb +204 -0
- data/test/recipe_test.rb +146 -0
- data/test/reliability_test.rb +60 -0
- data/test/reporter_test.rb +46 -0
- data/test/scm_test.rb +70 -0
- data/test/session_test.rb +49 -0
- data/test/test_helper.rb +96 -0
- data/test/tracing_test.rb +68 -0
- data/test/update_test.rb +42 -0
- data/version.yml +3 -0
- metadata +112 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
# (The MIT License)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2008 Jamis Buck <jamis@37signals.com>,
|
6
|
+
# with modifications by Bruce Williams <bruce@fiveruns.com>
|
7
|
+
#
|
8
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
# a copy of this software and associated documentation files (the
|
10
|
+
# 'Software'), to deal in the Software without restriction, including
|
11
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
# the following conditions:
|
15
|
+
#
|
16
|
+
# The above copyright notice and this permission notice shall be
|
17
|
+
# included in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
25
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
+
module Fiveruns
|
27
|
+
|
28
|
+
module Dash
|
29
|
+
|
30
|
+
# A class for describing the current version of a library. The version
|
31
|
+
# consists of three parts: the +major+ number, the +minor+ number, and the
|
32
|
+
# +tiny+ (or +patch+) number.
|
33
|
+
class Version
|
34
|
+
|
35
|
+
include Comparable
|
36
|
+
|
37
|
+
# A convenience method for instantiating a new Version instance with the
|
38
|
+
# given +major+, +minor+, and +tiny+ components.
|
39
|
+
def self.[](major, minor, tiny)
|
40
|
+
new(major, minor, tiny)
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :major, :minor, :tiny
|
44
|
+
|
45
|
+
# Create a new Version object with the given components.
|
46
|
+
def initialize(major, minor, tiny)
|
47
|
+
@major, @minor, @tiny = major, minor, tiny
|
48
|
+
end
|
49
|
+
|
50
|
+
# Compare this version to the given +version+ object.
|
51
|
+
def <=>(version)
|
52
|
+
to_i <=> version.to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
# Converts this version object to a string, where each of the three
|
56
|
+
# version components are joined by the '.' character. E.g., 2.0.0.
|
57
|
+
def to_s
|
58
|
+
@to_s ||= [@major, @minor, @tiny].join(".")
|
59
|
+
end
|
60
|
+
|
61
|
+
# Converts this version to a canonical integer that may be compared
|
62
|
+
# against other version objects.
|
63
|
+
def to_i
|
64
|
+
@to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_a
|
68
|
+
[@major, @minor, @tiny]
|
69
|
+
end
|
70
|
+
|
71
|
+
PARSED = YAML.load(File.read(File.dirname(__FILE__) << "/../../../version.yml"))
|
72
|
+
|
73
|
+
MAJOR = PARSED['major']
|
74
|
+
MINOR = PARSED['minor']
|
75
|
+
TINY = PARSED['patch']
|
76
|
+
|
77
|
+
# The current version as a Version instance
|
78
|
+
CURRENT = new(MAJOR, MINOR, TINY)
|
79
|
+
# The current version as a String
|
80
|
+
STRING = CURRENT.to_s
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
data/recipes/jruby.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# TODO Error Handling
|
2
|
+
# TODO cache VM and/or connection
|
3
|
+
# TODO singleton class around vm instance to avoid passing it all over the place
|
4
|
+
# should be able to do vm.connector_avaialble? and vm.load_management_agent
|
5
|
+
# TODO cache mbeans
|
6
|
+
# TODO more metprogramming in metrics area, pick up names and descriptions
|
7
|
+
# of attributes direct from mbean and expose all as metrics
|
8
|
+
|
9
|
+
if RUBY_PLATFORM[/java/]
|
10
|
+
|
11
|
+
require 'java'
|
12
|
+
|
13
|
+
import com.sun.tools.attach.VirtualMachine
|
14
|
+
import javax.management.remote.JMXServiceURL
|
15
|
+
import javax.management.remote.JMXConnectorFactory
|
16
|
+
import java.lang.management.ManagementFactory
|
17
|
+
import java.util.HashMap
|
18
|
+
|
19
|
+
module Fiveruns
|
20
|
+
module Dash
|
21
|
+
module JRuby
|
22
|
+
|
23
|
+
JMX_ADDRESS_PROPERTY = "com.sun.management.jmxremote.localConnectorAddress"
|
24
|
+
|
25
|
+
def self.connector_address_property( vm )
|
26
|
+
vm.getAgentProperties().getProperty(JMX_ADDRESS_PROPERTY)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.connector_available?( vm )
|
30
|
+
!connector_address_property( vm ).nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.load_management_agent( vm )
|
34
|
+
agent = vm.getSystemProperties().getProperty("java.home") + "/" + "lib" + "/" + "management-agent.jar"
|
35
|
+
vm.loadAgent( agent )
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.connector_address( vm )
|
39
|
+
load_management_agent( vm ) unless connector_available?( vm )
|
40
|
+
connector_address_property( vm )
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.connection #cache somehow ? instance variable? Not sure we're in a class ?
|
44
|
+
vm = VirtualMachine::attach( Process.pid.to_s )
|
45
|
+
url = JMXServiceURL.new( connector_address( vm ) )
|
46
|
+
connector = JMXConnectorFactory::connect url, HashMap.new
|
47
|
+
server_connection = connector.mbean_server_connection
|
48
|
+
server_connection
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.object_name(service_name)
|
52
|
+
"org.jruby:type=Runtime,name=#{::JRuby.runtime.hashCode},service=#{service_name}"
|
53
|
+
end
|
54
|
+
# e.g. mbean( "ClassCache", ClassCacheMBean::java_class)
|
55
|
+
# shold be able to DRY further - How to turn "ClassCache" into ClassCacheMBean::java_class
|
56
|
+
# not sure the pattern holds for everything, but it hold for everything here so far.
|
57
|
+
def self.mbean( service_name, java_class) # cache somehow? map lookup ? only need each bean proxy once.
|
58
|
+
ManagementFactory::newPlatformMXBeanProxy(connection, object_name(service_name), java_class)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Fiveruns::Dash.register_recipe :jruby, :url => 'http://dash.fiveruns.com' do |metrics|
|
66
|
+
|
67
|
+
# ############
|
68
|
+
# Class Cache MBean
|
69
|
+
# ############
|
70
|
+
|
71
|
+
import org.jruby.management.ClassCacheMBean
|
72
|
+
|
73
|
+
metrics.absolute :live_class_count, "Live Class Count", "Number of active classes" do
|
74
|
+
Integer(Fiveruns::Dash::JRuby.mbean("ClassCache", ClassCacheMBean::java_class).get_live_class_count)
|
75
|
+
end
|
76
|
+
metrics.absolute :class_load_count, "Class Load Count", "Number of loaded classes" do
|
77
|
+
Integer(Fiveruns::Dash::JRuby.mbean("ClassCache", ClassCacheMBean::java_class).get_class_load_count)
|
78
|
+
end
|
79
|
+
metrics.absolute :class_reuse_count, "Class Reuse Count", "Number of reused classes" do
|
80
|
+
Integer(Fiveruns::Dash::JRuby.mbean("ClassCache", ClassCacheMBean::java_class).get_class_reuse_count)
|
81
|
+
end
|
82
|
+
|
83
|
+
# ############
|
84
|
+
# JITCompiler MBean
|
85
|
+
# ############
|
86
|
+
|
87
|
+
import org.jruby.compiler.JITCompilerMBean
|
88
|
+
|
89
|
+
metrics.absolute :average_code_size, "Average Code Size", "Average Code Size" do
|
90
|
+
Integer(Fiveruns::Dash::JRuby.mbean("JITCompiler", JITCompilerMBean::java_class).average_code_size)
|
91
|
+
end
|
92
|
+
metrics.absolute :compile_count, "Compile Count", "Compile Count" do
|
93
|
+
Integer(Fiveruns::Dash::JRuby.mbean("JITCompiler", JITCompilerMBean::java_class).compile_count)
|
94
|
+
end
|
95
|
+
metrics.absolute :compile_success_count, "Compile Success Count", "Compile Success Count" do
|
96
|
+
Integer(Fiveruns::Dash::JRuby.mbean("JITCompiler", JITCompilerMBean::java_class).success_count)
|
97
|
+
end
|
98
|
+
metrics.absolute :compile_fail_count, "Compile Fail Count", "Compile Fail Count" do
|
99
|
+
Integer(Fiveruns::Dash::JRuby.mbean("JITCompiler", JITCompilerMBean::java_class).fail_count)
|
100
|
+
end
|
101
|
+
metrics.absolute :average_compile_time, "Average Compile Time", "Average Compile Time" do
|
102
|
+
Integer(Fiveruns::Dash::JRuby.mbean("JITCompiler", JITCompilerMBean::java_class).average_compile_time)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
data/recipes/ruby.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Fiveruns::Dash.register_recipe :ruby, :url => 'http://dash.fiveruns.com' do |metrics|
|
2
|
+
metrics.absolute :vsz,
|
3
|
+
"Virtual Memory Usage", "The amount of virtual memory used by this process",
|
4
|
+
:unit => 'kbytes', :scope => :host do
|
5
|
+
Integer(`ps -o vsz -p #{Process.pid}`[/(\d+)/, 1])
|
6
|
+
end
|
7
|
+
metrics.absolute :rss, "Resident Memory Usage",
|
8
|
+
"The amount of physical memory used by this process",
|
9
|
+
:unit => 'kbytes',
|
10
|
+
:scope => :host do
|
11
|
+
Integer(`ps -o rss -p #{Process.pid}`[/(\d+)/, 1])
|
12
|
+
end
|
13
|
+
metrics.percentage :pmem,
|
14
|
+
"Resident Memory Usage",
|
15
|
+
"Percentage of Resident Memory Usage",
|
16
|
+
:scope => :host do
|
17
|
+
Float(`ps -o pmem -p #{Process.pid}`[/(\d+\.\d+)/, 1])
|
18
|
+
end
|
19
|
+
|
20
|
+
if RUBY_PLATFORM == 'java'
|
21
|
+
Fiveruns::Dash.logger.warn "Cannot collect CPU usage data on JRuby"
|
22
|
+
else
|
23
|
+
metrics.percentage :cpu,
|
24
|
+
'CPU Usage',
|
25
|
+
'Percentage CPU Usage',
|
26
|
+
:scope => :host do
|
27
|
+
before = Thread.current[:dash_utime] ||= Process.times.utime
|
28
|
+
after = Process.times.utime
|
29
|
+
this_minute = after - before
|
30
|
+
Thread.current[:dash_utime] = after
|
31
|
+
(this_minute / 60) * 100.00
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
#require File.dirname(__FILE__) << "/test_helper"
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'shoulda'
|
5
|
+
require 'flexmock/test_unit'
|
6
|
+
require 'thread'
|
7
|
+
#require 'json'
|
8
|
+
require 'thin'
|
9
|
+
|
10
|
+
$:.unshift(File.dirname(__FILE__) << '/../lib')
|
11
|
+
# Require library files
|
12
|
+
require 'fiveruns/dash'
|
13
|
+
|
14
|
+
class Test::Unit::TestCase
|
15
|
+
include Fiveruns::Dash
|
16
|
+
end
|
17
|
+
|
18
|
+
class Integer
|
19
|
+
def intervals
|
20
|
+
self * 5 + 0.1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Fiveruns::Dash::Store::HTTP
|
25
|
+
def check_response_of(response)
|
26
|
+
unless response
|
27
|
+
Fiveruns::Dash.logger.debug "Received no response from Dash service"
|
28
|
+
return false
|
29
|
+
end
|
30
|
+
case response.code.to_i
|
31
|
+
when 201
|
32
|
+
true
|
33
|
+
when 400..499
|
34
|
+
Fiveruns::Dash.logger.warn "Could not access Dash service (#{response.code.to_i}, #{response.body.inspect})"
|
35
|
+
false
|
36
|
+
else
|
37
|
+
Fiveruns::Dash.logger.debug "Received unknown response from Dash service (#{response.inspect})"
|
38
|
+
false
|
39
|
+
end
|
40
|
+
rescue JSON::ParserError => e
|
41
|
+
puts response.body
|
42
|
+
Fiveruns::Dash.logger.error "Received non-JSON response (#{response.inspect})"
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class DummyCollector
|
48
|
+
attr_accessor :sleep_time, :data_payload_count, :info_payload_count, :post_times
|
49
|
+
|
50
|
+
def initialize(options = {})
|
51
|
+
@startup_delay = options[:startup_delay]
|
52
|
+
@response_delay = options[:response_delay]
|
53
|
+
@info_payload_count = 0
|
54
|
+
@data_payload_count = 0
|
55
|
+
@post_times = []
|
56
|
+
end
|
57
|
+
|
58
|
+
def call(t)
|
59
|
+
sleep(@sleep_time) if @sleep_time
|
60
|
+
puts "sleeping for #{@sleep_time}" if @sleep_time
|
61
|
+
@post_times << Time.now
|
62
|
+
res = nil
|
63
|
+
if t["rack.input"].read =~ /name=\"type\"\r\n\r\ninfo\r\n/
|
64
|
+
@info_payload_count += 1
|
65
|
+
res = info_response
|
66
|
+
else
|
67
|
+
@data_payload_count += 1
|
68
|
+
res = data_response
|
69
|
+
end
|
70
|
+
puts "BOOM! workers: info: #{@info_payload_count} data: #{@data_payload_count} #{Time.now} - #{Time.now.to_f}"
|
71
|
+
return [201, {"Content-Type" => "application/json; charset=utf-8" }, res]
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def info_response
|
76
|
+
data = {"process_id"=>774736468, "metric_infos"=>[{"name"=>"vsz", "id"=>932254202, "recipe_name"=>"ruby", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"rss", "id"=>932254199, "recipe_name"=>"ruby", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"pmem", "id"=>932254200, "recipe_name"=>"ruby", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"cpu", "id"=>932254201, "recipe_name"=>"ruby", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"activity", "id"=>932254194, "recipe_name"=>"activerecord", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"response_time", "id"=>932254195, "recipe_name"=>"actionpack", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"requests", "id"=>932254196, "recipe_name"=>"actionpack", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"render_time", "id"=>932254197, "recipe_name"=>"actionpack", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"queue_size", "id"=>932254198, "recipe_name"=>"rails", "recipe_url"=>"http://dash.fiveruns.com"}], "traces"=>[]}
|
77
|
+
return data.to_json
|
78
|
+
end
|
79
|
+
def data_response
|
80
|
+
data = {"process_id"=>774736448, "metric_infos"=>[{"name"=>"rss", "id"=>932254199, "recipe_name"=>"ruby", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"pmem", "id"=>932254200, "recipe_name"=>"ruby", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"cpu", "id"=>932254201, "recipe_name"=>"ruby", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"activity", "id"=>932254194, "recipe_name"=>"activerecord", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"response_time", "id"=>932254195, "recipe_name"=>"actionpack", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"requests", "id"=>932254196, "recipe_name"=>"actionpack", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"render_time", "id"=>932254197, "recipe_name"=>"actionpack", "recipe_url"=>"http://dash.fiveruns.com"}, {"name"=>"queue_size", "id"=>932254198, "recipe_name"=>"rails", "recipe_url"=>"http://dash.fiveruns.com"}], "traces"=>[]}
|
81
|
+
return data.to_json
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
class CollectorCommunicationTest < Test::Unit::TestCase
|
87
|
+
|
88
|
+
attr_reader :payload
|
89
|
+
context "FiveRuns Dash Gem" do
|
90
|
+
|
91
|
+
setup do
|
92
|
+
##no_recipe_loading!
|
93
|
+
flexmock(Fiveruns::Dash).should_receive(:load_recipes)
|
94
|
+
|
95
|
+
##mock_configuration!
|
96
|
+
@metrics = []
|
97
|
+
@metric_class = Class.new(Metric) do
|
98
|
+
def self.metric_type
|
99
|
+
:test
|
100
|
+
end
|
101
|
+
def info_id
|
102
|
+
1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
3.times do |i|
|
106
|
+
@metrics << @metric_class.new("Metric#{i}") { 1 }
|
107
|
+
end
|
108
|
+
@recipes = []
|
109
|
+
@recipes << Fiveruns::Dash::Recipe.new(:foo, :url => 'http://foo.com')
|
110
|
+
@recipes << Fiveruns::Dash::Recipe.new(:foo2, :url => 'http://foo2.com')
|
111
|
+
@metrics << @metric_class.new("NonCustomMetric") { 2 }
|
112
|
+
@configuration = flexmock(:configuration) do |mock|
|
113
|
+
mock.should_receive(:metrics).and_return(@metrics)
|
114
|
+
mock.should_receive(:recipes).and_return(@recipes)
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
##create_session!
|
119
|
+
@session = Session.new(@configuration)
|
120
|
+
|
121
|
+
# other stuff
|
122
|
+
flexmock(@configuration).should_receive(:options).and_return(:app => '123')
|
123
|
+
flexmock(::Fiveruns::Dash).should_receive(:configuration).and_return(@configuration)
|
124
|
+
flexmock(@session.reporter).should_receive(:update_locations).returns(["http://localhost:9999"])
|
125
|
+
|
126
|
+
@collector = DummyCollector.new()
|
127
|
+
@thin = Thin::Server.new('127.0.0.1', 9999, @collector)
|
128
|
+
@prev_value = Thread.abort_on_exception
|
129
|
+
Thread.abort_on_exception = true
|
130
|
+
end
|
131
|
+
|
132
|
+
teardown do
|
133
|
+
Thread.abort_on_exception = @prev_value
|
134
|
+
end
|
135
|
+
|
136
|
+
should "have no tests in here" do
|
137
|
+
assert true
|
138
|
+
end
|
139
|
+
|
140
|
+
should_eventually "act properly" do
|
141
|
+
# When the reporter starts, it immediately sends an info packet,
|
142
|
+
# along with a regular payload
|
143
|
+
@t = Thread.new { @thin.start }
|
144
|
+
@session.reporter.interval = 5
|
145
|
+
@session.reporter.start
|
146
|
+
sleep(2.intervals) #enough for 2 cycles
|
147
|
+
assert_equal @collector.info_payload_count, 1
|
148
|
+
assert_equal @collector.data_payload_count, 2
|
149
|
+
@thin.stop
|
150
|
+
assert_equal @collector.post_times.size, 3
|
151
|
+
@collector.post_times.size.times do |i|
|
152
|
+
unless i == (@collector.post_times.size - 1)
|
153
|
+
assert_equal (@collector.post_times[i+1].to_i - @collector.post_times[i].to_i), 5
|
154
|
+
end
|
155
|
+
end
|
156
|
+
@thin.stop!
|
157
|
+
puts "stopped!"
|
158
|
+
end
|
159
|
+
|
160
|
+
should_eventually "compensate correctly for delayed post times" do
|
161
|
+
@collector.sleep_time = 2
|
162
|
+
@t = Thread.new { @thin.start }
|
163
|
+
@session.reporter.interval = 5
|
164
|
+
@session.reporter.start
|
165
|
+
sleep(2.intervals + @collector.sleep_time ) #enough for 2 cycles
|
166
|
+
assert_equal @collector.info_payload_count, 1
|
167
|
+
assert_equal @collector.data_payload_count, 2
|
168
|
+
@thin.stop
|
169
|
+
assert_equal @collector.post_times.size, 3
|
170
|
+
@collector.post_times.size.times do |i|
|
171
|
+
unless i == (@collector.post_times.size - 1)
|
172
|
+
assert_equal (@collector.post_times[i+1].to_i - @collector.post_times[i].to_i), 5
|
173
|
+
end
|
174
|
+
end
|
175
|
+
@thin.stop!
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
should_eventually "continue to report if the first payload fails" do
|
180
|
+
@session.reporter.interval = 5
|
181
|
+
@session.reporter.start
|
182
|
+
sleep(1.intervals)
|
183
|
+
assert_equal @collector.data_payload_count, 0
|
184
|
+
assert_equal @collector.data_payload_count, 0
|
185
|
+
#puts "STARTING COLLECTOR #{Time.now}"
|
186
|
+
@t = Thread.new { @thin.start }
|
187
|
+
#puts "COLLECTOR STARTED #{Time.now} - #{Time.now.to_f}"
|
188
|
+
#puts "STARTING SLEEP #{Time.now} - #{Time.now.to_f}"
|
189
|
+
sleep(2.intervals)
|
190
|
+
#puts "DONE SLEEPING #{Time.now} - #{Time.now.to_f}"
|
191
|
+
assert_equal @collector.info_payload_count, 1
|
192
|
+
assert_equal @collector.data_payload_count, 1
|
193
|
+
@thin.stop!
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
should_eventually "continue to report if collector dies at a random time" do
|
198
|
+
@t = Thread.new { @thin.start }
|
199
|
+
@session.reporter.interval = 5
|
200
|
+
@session.reporter.start
|
201
|
+
sleep(2.intervals)
|
202
|
+
puts "STOPPING!!! #{Time.now}"
|
203
|
+
@thin.stop!
|
204
|
+
@t.kill
|
205
|
+
puts "STOPPED #{Time.now}"
|
206
|
+
assert_equal @collector.info_payload_count, 1
|
207
|
+
assert_equal @collector.data_payload_count, 2
|
208
|
+
sleep(3.intervals) #stop for a while
|
209
|
+
puts "STARTING BACK UP #{Time.now}"
|
210
|
+
@t = Thread.new { @thin.start }
|
211
|
+
puts "STARTED BACK UP #{Time.now}"
|
212
|
+
sleep(3.intervals)
|
213
|
+
puts "STOPPING AGAIN!!! #{Time.now}"
|
214
|
+
@thin.stop
|
215
|
+
puts "STOPPED FINALLY #{Time.now}"
|
216
|
+
assert_equal @collector.data_payload_count, 5
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
# check the post time intervals to make sure they match what we expect
|
221
|
+
(0..1).each do |i|
|
222
|
+
assert_equal((@collector.post_times[i+1].to_i - @collector.post_times[i].to_i), 5)
|
223
|
+
end
|
224
|
+
# because we shut down for 3 intervals, the next post wouldn't happen until the 4th interval
|
225
|
+
# thus, 20 seconds
|
226
|
+
assert_equal (@collector.post_times[3].to_i - @collector.post_times[2].to_i), 20
|
227
|
+
(3..4).each do |i|
|
228
|
+
assert_equal((@collector.post_times[i+1].to_i - @collector.post_times[i].to_i), 5)
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
#######
|
237
|
+
private
|
238
|
+
#######
|
239
|
+
|
240
|
+
def full_urls(service)
|
241
|
+
full_uris(service).map(&:to_s)
|
242
|
+
end
|
243
|
+
|
244
|
+
def full_uris(service)
|
245
|
+
@urls.map do |url|
|
246
|
+
uri = URI.parse(url)
|
247
|
+
uri.path = if service == :exceptions
|
248
|
+
'/exceptions.json'
|
249
|
+
else
|
250
|
+
"/apps/123/#{service}.json"
|
251
|
+
end
|
252
|
+
uri
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def uris
|
257
|
+
@urls.map { |url| URI.parse(url) }
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|