fiveruns-dash-ruby 0.7.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/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
|