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 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