scout 5.4.5.1.alpha → 5.4.6.alpha
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/lib/scout/plugin.rb +0 -9
- data/lib/scout/streamer.rb +85 -65
- data/lib/scout/version.rb +1 -1
- data/test/scout_test.rb +39 -7
- metadata +5 -5
data/lib/scout/plugin.rb
CHANGED
@@ -133,15 +133,6 @@ module Scout
|
|
133
133
|
END
|
134
134
|
end
|
135
135
|
|
136
|
-
# resets everything except memory. Memory stays intact. This is used for real-time reporting
|
137
|
-
def reset!
|
138
|
-
@data_for_server = { :reports => [ ],
|
139
|
-
:alerts => [ ],
|
140
|
-
:errors => [ ],
|
141
|
-
:summaries => [ ],
|
142
|
-
:memory => @memory }
|
143
|
-
end
|
144
|
-
|
145
136
|
#
|
146
137
|
# Usage:
|
147
138
|
#
|
data/lib/scout/streamer.rb
CHANGED
@@ -30,45 +30,43 @@ module Scout
|
|
30
30
|
load_history
|
31
31
|
|
32
32
|
# get the array of plugins, AKA the plugin plan
|
33
|
-
@
|
34
|
-
info("Starting streamer with key=#{streaming_key} and plugin_ids: #{plugin_ids.inspect}. #{@history_file} includes plugin ids #{@
|
33
|
+
@all_plugins = Array(@history["old_plugins"])
|
34
|
+
info("Starting streamer with key=#{streaming_key} and plugin_ids: #{plugin_ids.inspect}. #{@history_file} includes plugin ids #{@all_plugins.map{|p|p['id']}.inspect}")
|
35
35
|
|
36
|
-
#
|
37
|
-
|
38
|
-
plugin_data=@plugin_plan.find{|plugin| plugin['id'] && plugin['id'].to_i == plugin_id}
|
39
|
-
if plugin_data
|
40
|
-
begin
|
41
|
-
plugin=get_instance_of(plugin_data, plugin_id)
|
42
|
-
info("#{i+1}) plugin_id=#{plugin_id} - instance of #{plugin.class.name} created for #{plugin_data['name']}" )
|
43
|
-
if plugin.is_a?(Plugin) # safety check that it's an instance of Plugin
|
44
|
-
@plugin_hashes.push(:instance=>plugin, :id=>plugin_id, :name=>plugin_data['name'])
|
45
|
-
end
|
46
|
-
rescue Exception
|
47
|
-
error("Encountered an error compiling: #{$!.message}")
|
48
|
-
error $!.backtrace.join('\n')
|
49
|
-
end
|
50
|
-
else
|
51
|
-
info("#{i+1}) plugin_id=#{plugin_id} specified in #{plugin_ids.inspect} but not found in #{@history_file}")
|
52
|
-
end
|
53
|
-
end
|
36
|
+
# selected_plugins is subset of the @all_plugins -- those selected in plugin_ids
|
37
|
+
selected_plugins = compile_plugins(@all_plugins, plugin_ids)
|
54
38
|
|
55
|
-
info "Finished compilation. #{@plugin_plan.size} plugins; #{@plugin_hashes.size} instances instantiated"
|
56
39
|
|
57
40
|
# main loop. Continue running until global $continue_streaming is set to false OR we've been running for MAX DURATION
|
58
41
|
iteration=1 # use this to log the data at a couple points
|
59
42
|
while(streamer_start_time+MAX_DURATION > Time.now && $continue_streaming) do
|
60
43
|
plugins=[]
|
61
|
-
|
62
|
-
plugin
|
44
|
+
selected_plugins.each_with_index do |plugin_hash,i|
|
45
|
+
# create an actual instance of the plugin
|
46
|
+
plugin=get_instance_of(plugin_hash)
|
47
|
+
|
63
48
|
start_time=Time.now
|
64
|
-
|
65
|
-
|
49
|
+
|
50
|
+
data = {}
|
51
|
+
begin
|
52
|
+
Timeout.timeout(30, PluginTimeoutError) do
|
53
|
+
data = plugin.run
|
54
|
+
end
|
55
|
+
rescue Timeout::Error, PluginTimeoutError
|
56
|
+
error "Plugin took too long to run."
|
57
|
+
end
|
58
|
+
|
66
59
|
duration=((Time.now-start_time)*1000).to_i
|
67
60
|
|
61
|
+
id_and_name = plugin_hash['id_and_name']
|
62
|
+
@history["last_runs"][id_and_name] = start_time
|
63
|
+
@history["memory"][id_and_name] = data[:memory]
|
64
|
+
|
68
65
|
plugins << {:duration=>duration,
|
69
66
|
:fields=>plugin.reports.inject{|memo,hash|memo.merge(hash)},
|
70
|
-
:name=>plugin_hash[
|
71
|
-
:id=>plugin_hash[
|
67
|
+
:name=>plugin_hash['name'],
|
68
|
+
:id=>plugin_hash['id'],
|
69
|
+
:class=>plugin_hash['code_class']}
|
72
70
|
end
|
73
71
|
|
74
72
|
bundle={:hostname=>hostname,
|
@@ -76,6 +74,7 @@ module Scout
|
|
76
74
|
:num_processes=>`ps -e | wc -l`.chomp.to_i,
|
77
75
|
:plugins=>plugins }
|
78
76
|
|
77
|
+
# stream the data via pusherapp
|
79
78
|
begin
|
80
79
|
Pusher[streaming_key].trigger!('server_data', bundle)
|
81
80
|
rescue Pusher::Error => e
|
@@ -85,15 +84,7 @@ module Scout
|
|
85
84
|
|
86
85
|
if iteration == 2 || iteration == 100
|
87
86
|
info "Run #{iteration} data dump:"
|
88
|
-
info bundle.
|
89
|
-
end
|
90
|
-
|
91
|
-
if false
|
92
|
-
# debugging
|
93
|
-
File.open(File.join(File.dirname(@history_file),"debug.txt"),"w") do |f|
|
94
|
-
f.puts "... sleeping @ #{Time.now.strftime("%I:%M:%S %p")}..."
|
95
|
-
f.puts bundle.to_yaml
|
96
|
-
end
|
87
|
+
info bundle.inspect
|
97
88
|
end
|
98
89
|
|
99
90
|
sleep(SLEEP)
|
@@ -106,42 +97,71 @@ module Scout
|
|
106
97
|
|
107
98
|
private
|
108
99
|
|
109
|
-
#
|
110
|
-
|
111
|
-
|
100
|
+
# Compile instances of the plugins specified in the passed plugin_ids
|
101
|
+
def compile_plugins(all_plugins,plugin_ids)
|
102
|
+
num_classes_compiled=0
|
103
|
+
selected_plugins=[]
|
104
|
+
plugin_ids.each_with_index do |plugin_id,i|
|
105
|
+
plugin=all_plugins.find{|plugin| plugin['id'] && plugin['id'].to_i == plugin_id}
|
106
|
+
if plugin
|
107
|
+
begin
|
108
|
+
# take care of plugin overrides
|
109
|
+
local_path = File.join(File.dirname(@history_file), "#{plugin_id}.rb")
|
110
|
+
if File.exist?(local_path)
|
111
|
+
code_to_run = File.read(local_path)
|
112
|
+
else
|
113
|
+
code_to_run=plugin['code'] || ""
|
114
|
+
end
|
112
115
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
code_class=Plugin.extract_code_class(code_to_run)
|
117
|
+
|
118
|
+
# eval the plugin code if it's not already defined
|
119
|
+
if !Object.const_defined?(code_class)
|
120
|
+
eval(code_to_run, TOPLEVEL_BINDING, plugin['name'] )
|
121
|
+
|
122
|
+
# turn certain methods into null-ops, so summaries aren't generated. Note that this is ad-hoc, and not future-proof.
|
123
|
+
klass=Scout::Plugin.const_get(code_class)
|
124
|
+
if code_class=="RailsRequests"
|
125
|
+
klass.module_eval { def analyze;end; }
|
126
|
+
end
|
127
|
+
if code_class=="ApacheAnalyzer"
|
128
|
+
klass.module_eval { def generate_log_analysis;end; }
|
129
|
+
end
|
130
|
+
info "#{i+1}) #{plugin['name']} (id=#{plugin_id}) - #{code_class} compiled."
|
131
|
+
num_classes_compiled+=1
|
132
|
+
else
|
133
|
+
info "#{i+1}) #{plugin['name']} (id=#{plugin_id}) - #{code_class} was compiled previously."
|
134
|
+
end
|
135
|
+
# we'll use code_class and id_and name again
|
136
|
+
plugin['code_class']=code_class
|
137
|
+
plugin['id_and_name']= "#{plugin['id']}-#{plugin['name']}".sub(/\A-/, "")
|
138
|
+
selected_plugins << plugin
|
139
|
+
rescue Exception
|
140
|
+
error("Encountered an error compiling: #{$!.message}")
|
141
|
+
error $!.backtrace.join('\n')
|
142
|
+
end
|
143
|
+
else
|
144
|
+
info("#{i+1}) plugin_id=#{plugin_id} specified in #{plugin_ids.inspect} but not found in #{@history_file}")
|
145
|
+
end
|
119
146
|
end
|
120
147
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
memory = @history["memory"][id_and_name] ||
|
125
|
-
@history["memory"][plugin['name']]
|
126
|
-
options=(plugin['options'] || Hash.new)
|
127
|
-
options.merge!(:tuner_days=>"")
|
128
|
-
|
129
|
-
code_class=Plugin.extract_code_class(code_to_run)
|
130
|
-
|
131
|
-
# eval the plugin code if it's not already defined
|
132
|
-
if !Plugin.const_defined?(code_class)
|
133
|
-
eval(code_to_run, TOPLEVEL_BINDING, plugin['path'] || plugin['name'] )
|
134
|
-
end
|
148
|
+
info "Finished compilation. #{num_classes_compiled} plugin classes compiled for the #{plugin_ids.size} plugin(s) needed for streaming."
|
149
|
+
return selected_plugins
|
150
|
+
end
|
135
151
|
|
136
|
-
|
137
|
-
|
152
|
+
# plugin is a hash of plugin data from the history file (id, name, code, etc).
|
153
|
+
# This plugin returns an instantiated instance of the plugin
|
154
|
+
def get_instance_of(plugin)
|
138
155
|
|
139
|
-
|
140
|
-
|
141
|
-
|
156
|
+
id_and_name = plugin['id_and_name']
|
157
|
+
last_run = @history["last_runs"][id_and_name]
|
158
|
+
memory = @history["memory"][id_and_name]
|
159
|
+
options=(plugin['options'] || Hash.new)
|
160
|
+
options.merge!(:tuner_days=>"")
|
142
161
|
|
143
162
|
# finally, return an instance of the plugin
|
144
|
-
klass.
|
163
|
+
klass=Scout::Plugin.const_get(plugin['code_class'])
|
164
|
+
return klass.load(last_run, (memory || Hash.new), options)
|
145
165
|
end
|
146
166
|
|
147
167
|
|
data/lib/scout/version.rb
CHANGED
data/test/scout_test.rb
CHANGED
@@ -410,7 +410,7 @@ mybar=100
|
|
410
410
|
scout(@client.key) # to write the initial history file. Sinatra MUST be running
|
411
411
|
$continue_streaming = true # so the streamer will run once
|
412
412
|
streamer=Scout::Streamer.new("http://none", "bogus_client_key", PATH_TO_DATA_FILE, [@client.plugins.first.id]+plugins.map(&:id), "bogus_streaming_key",nil) # for debugging, make last arg Logger.new(STDOUT)
|
413
|
-
res =
|
413
|
+
res = Pusher::Channel.streamer_data # via the mock_streamer call
|
414
414
|
|
415
415
|
assert res.is_a?(Hash)
|
416
416
|
assert res[:plugins].is_a?(Array)
|
@@ -422,6 +422,7 @@ mybar=100
|
|
422
422
|
end # end of mock_pusher
|
423
423
|
end
|
424
424
|
|
425
|
+
# the local plugin shouldn't report
|
425
426
|
def test_streamer_with_local_plugin
|
426
427
|
local_path=File.join(AGENT_DIR,"my_local_plugin.rb")
|
427
428
|
code=<<-EOC
|
@@ -435,11 +436,11 @@ mybar=100
|
|
435
436
|
mock_pusher do
|
436
437
|
$continue_streaming = true # so the streamer will run once
|
437
438
|
streamer=Scout::Streamer.new("http://none", "bogus_client_key", PATH_TO_DATA_FILE, [@client.plugins.first.id], "bogus_streaming_key",nil) # for debugging, make last arg Logger.new(STDOUT)
|
438
|
-
res =
|
439
|
+
res = Pusher::Channel.streamer_data # Pusher::Channel.streamer_data via the mock_streamer call
|
439
440
|
|
440
441
|
assert res.is_a?(Hash)
|
441
442
|
assert res[:plugins].is_a?(Array)
|
442
|
-
assert_equal 1, res[:plugins].size
|
443
|
+
assert_equal 1, res[:plugins].size # this is NOT the local plugin, it's a regular plugin that's already there
|
443
444
|
assert_equal 2, res[:plugins][0][:fields][:load]
|
444
445
|
end # end of mock_pusher
|
445
446
|
end
|
@@ -469,6 +470,20 @@ mybar=100
|
|
469
470
|
assert_nil @client.reload.streamer_command
|
470
471
|
end
|
471
472
|
|
473
|
+
def test_streamer_with_memory
|
474
|
+
mock_pusher(3) do
|
475
|
+
plugin = create_plugin(@client, "memory plugin", PLUGIN_FIXTURES[:memory][:code], PLUGIN_FIXTURES[:memory][:sig])
|
476
|
+
scout(@client.key)
|
477
|
+
#puts YAML.load(File.read(PATH_TO_DATA_FILE))['memory'].to_yaml
|
478
|
+
|
479
|
+
$continue_streaming = true # so the streamer will start running
|
480
|
+
# for debugging, make last arg Logger.new(STDOUT)
|
481
|
+
streamer=Scout::Streamer.new("http://none", "bogus_client_key", PATH_TO_DATA_FILE, [plugin.id], "bogus_streaming_key",nil)
|
482
|
+
res = Pusher::Channel.streamer_data # Pusher::Channel.streamer_data via the mock_pusher call
|
483
|
+
assert_equal 3, res[:plugins][0][:fields][:v], "after the two streamer runs, this plugin should report v=3 -- it increments each run"
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
472
487
|
|
473
488
|
######################
|
474
489
|
### Helper Methods ###
|
@@ -585,16 +600,23 @@ mybar=100
|
|
585
600
|
p
|
586
601
|
end
|
587
602
|
|
588
|
-
# this with a block to mock the pusher call. You can access the streamer data through the
|
603
|
+
# this with a block to mock the pusher call. You can access the streamer data through the Pusher::Channel.streamer_data
|
589
604
|
# Must be called with a code block
|
590
|
-
def mock_pusher
|
605
|
+
def mock_pusher(num_runs=1)
|
591
606
|
# redefine the trigger! method, so the streamer doesn't loop indefinitely. We can't just mock it, because
|
592
607
|
# we need to set the $continue_streaming=false
|
608
|
+
$num_runs_for_mock_pusher=num_runs
|
593
609
|
Pusher::Channel.module_eval do
|
594
610
|
alias orig_trigger! trigger!
|
611
|
+
def self.streamer_data;@@streamer_data;end # for getting the data back out
|
595
612
|
def trigger!(event_name, data, socket=nil)
|
596
|
-
|
597
|
-
$
|
613
|
+
@num_run_for_tests = @num_run_for_tests ? @num_run_for_tests+1 : 1
|
614
|
+
# puts "in mock pusher trigger! This is run #{@num_run_for_tests} of #{$num_runs_for_mock_pusher}"
|
615
|
+
@@streamer_data = data
|
616
|
+
if @num_run_for_tests >= $num_runs_for_mock_pusher
|
617
|
+
$continue_streaming=false
|
618
|
+
@num_run_for_tests=nil
|
619
|
+
end
|
598
620
|
end
|
599
621
|
end
|
600
622
|
yield # must be called with a block
|
@@ -624,6 +646,16 @@ v6GYcfGCAsiZvnjl/2wsqjvrAl/zyuSW/s5YLsjxca1LEvhkyxbpnDGuj32k
|
|
624
646
|
7gtxXcblNP6hm7A6AlBzP0hwYORR//gpLLGtmT5ewltHUj9aSUY0GQle3lvH
|
625
647
|
/uzBDoV1x6mEYR2jPO5QQxL3BvTBvpC06ec8M/ZWbO9IwA7/DOs+vYfngxlp
|
626
648
|
jbtpAK9QCaAalKy/Z29os/7aViHy9z9IVCpC/z3MDA==
|
649
|
+
EOS
|
650
|
+
},
|
651
|
+
:memory=>{:code=>"class MemoryPlugin < Scout::Plugin;def build_report; v=memory(:v)||0; report(:v=>v);remember(:v,v+1);end;end",
|
652
|
+
:sig=><<EOS
|
653
|
+
5GNahpevN9VW5f7rmo6Cfq+2TWp8pwukxbE5laAZtDea44KaNE9gSMfiNCqz
|
654
|
+
rLAHvNXITJi0uI1rm+HXrak6L5oGvSouivCPtPTq1jRBy4QX2Sk9+gNEtTa8
|
655
|
+
HXu5TIQLJ/+IYHIG2E5FWcbfddR8cmJkIl4zGs93IatQNTENksRzphob7Cz8
|
656
|
+
wBwOHDG78kJ4TWEV5NIa5rLW8y2ltthfEPCTnS8/Zxa6h0qFtNrUWiU2KKtp
|
657
|
+
xTbJ3RgWKUnAR3YrEGB/JjjkPN2FrsDRvlClGujaYIWpWGkf+GZcpUn+QYxP
|
658
|
+
w7/kFz29Ds4hJRg2E2cWCHPtrD4dI0p/1iwP4XsxOw==
|
627
659
|
EOS
|
628
660
|
}
|
629
661
|
} # end of PLUGIN_FIXTURES
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.4.
|
5
|
-
prerelease:
|
4
|
+
version: 5.4.6.alpha
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andre Lewis
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2011-12-
|
14
|
+
date: 2011-12-17 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: elif
|
18
|
-
requirement: &
|
18
|
+
requirement: &70103547353160 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
version: '0'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70103547353160
|
27
27
|
description: ! 'Scout makes monitoring and reporting on your web applications as flexible
|
28
28
|
and simple as possible.
|
29
29
|
|