scout 5.4.5.1.alpha → 5.4.6.alpha

Sign up to get free protection for your applications and to get access to all the features.
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
  #
@@ -30,45 +30,43 @@ module Scout
30
30
  load_history
31
31
 
32
32
  # get the array of plugins, AKA the plugin plan
33
- @plugin_plan = Array(@history["old_plugins"])
34
- info("Starting streamer with key=#{streaming_key} and plugin_ids: #{plugin_ids.inspect}. #{@history_file} includes plugin ids #{@plugin_plan.map{|p|p['id']}.inspect}")
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
- # Compile instances of the plugins specified in the passed plugin_ids
37
- plugin_ids.each_with_index do |plugin_id,i|
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
- @plugin_hashes.each_with_index do |plugin_hash,i|
62
- plugin=plugin_hash[:instance]
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
- plugin.reset!
65
- plugin.run
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[:name],
71
- :id=>plugin_hash[:id]}
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.to_json
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
- # plugin is a hash of plugin data from the history file (id, name, code, etc).
110
- # This plugin returns an instantiated instance of the plugin
111
- def get_instance_of(plugin, plugin_id)
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
- # take care of plugin overrides
114
- local_path = File.join(File.dirname(@history_file), "#{plugin_id}.rb")
115
- if File.exist?(local_path)
116
- code_to_run = File.read(local_path)
117
- else
118
- code_to_run=plugin['code'] || ""
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
- id_and_name = "#{plugin_id}-#{plugin['name']}".sub(/\A-/, "")
122
- last_run = @history["last_runs"][id_and_name] ||
123
- @history["last_runs"][plugin['name']]
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
- # now that we know the class is defined, reference its class
137
- klass=Scout::Plugin.const_get(code_class)
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
- # turn certain methods into null-ops, so summaries aren't generated. Note that this is ad-hoc, and not future-proof.
140
- if klass.name=="RailsRequests"; def klass.analyze;end;end
141
- if klass.name=="ApacheAnalyzer"; def klass.generate_log_analysis;end;end
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.load(last_run, (memory || Hash.new), options)
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
@@ -1,3 +1,3 @@
1
1
  module Scout
2
- VERSION = "5.4.5.1.alpha"
2
+ VERSION = "5.4.6.alpha"
3
3
  end
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 = $streamer_data # $streamer_data via the mock_streamer call
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 = $streamer_data # $streamer_data via the mock_streamer call
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 global $streamer_data
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
- $streamer_data = data
597
- $continue_streaming=false
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.1.alpha
5
- prerelease: 8
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 00:00:00.000000000 Z
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: &70137852313700 !ruby/object:Gem::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: *70137852313700
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