scout 5.4.4.alpha → 5.4.5.alpha

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -4,3 +4,6 @@ pkg/*
4
4
  **/.DS_Store
5
5
  .idea
6
6
  working_dir/
7
+ .bundle
8
+ .rvmrc
9
+ Gemfile.lock
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in scout.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem "newrelic_rpm"
8
+ gem "activerecord", "2.2.2"
9
+ gem "mysql"
10
+ end
data/Rakefile CHANGED
@@ -5,3 +5,7 @@ require "bundler/gem_tasks"
5
5
  # rake build # Builds gem into the pkg directory
6
6
  # rake install # Build and install the current version into system gems
7
7
  # rake release # Create, tag, build, and publish the current version to rubygems.org
8
+
9
+ task :test do
10
+ require "test/scout_test"
11
+ end
@@ -15,40 +15,51 @@ module Scout
15
15
  @history = Hash.new
16
16
  @logger = logger
17
17
 
18
- @plugins = []
18
+ @plugin_hashes = []
19
19
 
20
20
  Pusher.app_id = '11495'
21
21
  Pusher.key = 'a95aa7293cd158100246'
22
22
  Pusher.secret = '9c13ccfe325fe3ae682d'
23
23
 
24
- debug "plugin_ids = #{plugin_ids.inspect}"
25
- debug "streaming_key = #{streaming_key}"
26
-
27
24
  streamer_start_time = Time.now
28
25
 
26
+ info("Streamer PID=#{$$} starting")
27
+
29
28
  hostname=Socket.gethostname
30
29
  # load history
31
30
  load_history
32
31
 
33
32
  # get the array of plugins, AKA the plugin plan
34
33
  @plugin_plan = Array(@history["old_plugins"])
35
-
36
- # iterate through the plan and compile each plugin. We only compile plugins once at the beginning of the run
37
- @plugin_plan.each do |plugin|
38
- begin
39
- compile_plugin(plugin) # this is what adds to the @plugin array
40
- rescue Exception
41
- error("Encountered an error: #{$!.message}")
42
- puts $!.backtrace.join('\n')
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}")
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}")
43
52
  end
44
53
  end
45
54
 
55
+ info "Finished compilation. #{@plugin_plan.size} plugins; #{@plugin_hashes.size} instances instantiated"
56
+
46
57
  # main loop. Continue running until global $continue_streaming is set to false OR we've been running for MAX DURATION
58
+ iteration=1 # use this to log the data at a couple points
47
59
  while(streamer_start_time+MAX_DURATION > Time.now && $continue_streaming) do
48
60
  plugins=[]
49
- @plugins.each_with_index do |plugin,i|
50
- # ignore plugins whose ids are not in the plugin_ids array -- this also ignores local plugins
51
- next if !(@plugin_plan[i]['id'] && plugin_ids.include?(@plugin_plan[i]['id'].to_i))
61
+ @plugin_hashes.each_with_index do |plugin_hash,i|
62
+ plugin=plugin_hash[:instance]
52
63
  start_time=Time.now
53
64
  plugin.reset!
54
65
  plugin.run
@@ -56,8 +67,8 @@ module Scout
56
67
 
57
68
  plugins << {:duration=>duration,
58
69
  :fields=>plugin.reports.inject{|memo,hash|memo.merge(hash)},
59
- :name=>@plugin_plan[i]["name"],
60
- :id=>@plugin_plan[i]["id"]}
70
+ :name=>plugin_hash[:name],
71
+ :id=>plugin_hash[:id]}
61
72
  end
62
73
 
63
74
  bundle={:hostname=>hostname,
@@ -72,6 +83,11 @@ module Scout
72
83
  error "Error pushing data: #{e.message}"
73
84
  end
74
85
 
86
+ if iteration == 2 || iteration == 100
87
+ info "Run #{iteration} data dump:"
88
+ info bundle.to_json
89
+ end
90
+
75
91
  if false
76
92
  # debugging
77
93
  File.open(File.join(File.dirname(@history_file),"debug.txt"),"w") do |f|
@@ -81,27 +97,18 @@ module Scout
81
97
  end
82
98
 
83
99
  sleep(SLEEP)
100
+ iteration+=1
84
101
  end
102
+
103
+ info("Streamer PID=#{$$} ending.")
85
104
  end
86
105
 
87
106
 
88
107
  private
89
108
 
90
- #def post_bundle(bundle)
91
- # post( urlify(:stream),
92
- # "Unable to stream to server.",
93
- # bundle.to_json,
94
- # "Content-Type" => "application/json")
95
- #rescue Exception
96
- # error "Unable to stream to server."
97
- # debug $!.class.to_s
98
- # debug $!.message
99
- # debug $!.backtrace.join("\n")
100
- #end
101
-
102
- # sets up the @plugins array
103
- def compile_plugin(plugin)
104
- plugin_id = plugin['id']
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)
105
112
 
106
113
  # take care of plugin overrides
107
114
  local_path = File.join(File.dirname(@history_file), "#{plugin_id}.rb")
@@ -111,27 +118,30 @@ module Scout
111
118
  code_to_run=plugin['code'] || ""
112
119
  end
113
120
 
114
- id_and_name = "#{plugin['id']}-#{plugin['name']}".sub(/\A-/, "")
121
+ id_and_name = "#{plugin_id}-#{plugin['name']}".sub(/\A-/, "")
115
122
  last_run = @history["last_runs"][id_and_name] ||
116
123
  @history["last_runs"][plugin['name']]
117
124
  memory = @history["memory"][id_and_name] ||
118
125
  @history["memory"][plugin['name']]
119
126
  options=(plugin['options'] || Hash.new)
120
127
  options.merge!(:tuner_days=>"")
128
+
121
129
  code_class=Plugin.extract_code_class(code_to_run)
122
- begin
130
+
131
+ # eval the plugin code if it's not already defined
132
+ if !Plugin.const_defined?(code_class)
123
133
  eval(code_to_run, TOPLEVEL_BINDING, plugin['path'] || plugin['name'] )
124
- klass=Plugin.const_get(code_class)
125
- info "Added a #{klass.name} plugin, id = #{plugin_id}"
126
- @plugins << klass.load(last_run, (memory || Hash.new), options)
134
+ end
127
135
 
128
- # turn certain methods into null-ops, so summaries aren't generated. Note that this is ad-hoc, and not future-proof.
129
- if klass.name=="RailsRequests"; def klass.analyze;end;end
130
- if klass.name=="ApacheAnalyzer"; def klass.generate_log_analysis;end;end
136
+ # now that we know the class is defined, reference its class
137
+ klass=Scout::Plugin.const_get(code_class)
131
138
 
132
- rescue Exception
133
- error "Plugin would not compile: #{$!.message}"
134
- end
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
142
+
143
+ # finally, return an instance of the plugin
144
+ klass.load(last_run, (memory || Hash.new), options)
135
145
  end
136
146
 
137
147
 
@@ -156,7 +166,5 @@ module Scout
156
166
  end
157
167
  end
158
168
 
159
- def growl(message)`growlnotify -m '#{message.gsub("'","\'")}'`;end
160
-
161
169
  end
162
170
  end
@@ -3,12 +3,12 @@ module Scout
3
3
 
4
4
  # args are: server, key, history, plugin_ids, streaming_key, log
5
5
  def start(args)
6
- puts "StreamerControl#start PID=#{pid}"
6
+ #puts "StreamerControl#start PID=#{pid}"
7
7
  server,key,history,plugin_ids,streaming_key,log = args
8
- $continue_streaming = true #
8
+ $continue_streaming = true #needed for streamer to loop
9
9
 
10
10
  @scout = Scout::Streamer.new(server, key, history, plugin_ids, streaming_key, log)
11
- puts "StreamerControl - done. Removing pid_file at #{pid_file} containing PID=#{pid}"
11
+ # puts "StreamerControl - done. Removing pid_file at #{pid_file} containing PID=#{pid}"
12
12
  File.unlink(pid_file) if File.exists?(pid_file) # a better way of doing this?
13
13
  end
14
14
 
data/lib/scout/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Scout
2
- VERSION = "5.4.4.alpha"
2
+ VERSION = "5.4.5.alpha"
3
3
  end
data/test/scout_test.rb CHANGED
@@ -5,6 +5,7 @@
5
5
  #
6
6
  $VERBOSE=nil
7
7
  $LOAD_PATH << File.expand_path( File.dirname(__FILE__) + '/../lib' )
8
+ $LOAD_PATH << File.expand_path( File.dirname(__FILE__) + '/..' )
8
9
  require 'test/unit'
9
10
  require 'lib/scout'
10
11
  require "pty"
@@ -392,66 +393,58 @@ mybar=100
392
393
  File.open(local_path,"w"){|f|f.write(code)}
393
394
 
394
395
  scout(@client.key)
395
-
396
396
  assert_equal plugin_count+1, @client.reload.plugins.count, "there should be one additional plugin records -- created from the local plugin"
397
-
398
397
  File.delete(local_path)
399
398
  end
400
399
 
400
+ # Streamer tests
401
401
 
402
+ # includes two plugins of the same class
402
403
  def test_streamer_plugin_compilation
403
- # redefine the trigger! method, so the streamer doesn't loop indefinitely. We can't just mock it, because
404
- # we need to set the $continue_streaming=false
405
- Pusher::Channel.module_eval do
406
- alias orig_trigger! trigger!
407
- def trigger!(event_name, data, socket=nil)
408
- $streamer_data = data
409
- $continue_streaming=false
404
+ mock_pusher do
405
+ plugins=[]
406
+ plugins << create_plugin(@client, "AclPlugin_1", PLUGIN_FIXTURES[:acl][:code], PLUGIN_FIXTURES[:acl][:sig])
407
+ plugins << create_plugin(@client, "XYZ Plugin", PLUGIN_FIXTURES[:xyz][:code], PLUGIN_FIXTURES[:xyz][:sig])
408
+ plugins << create_plugin(@client, "AclPlugin_2", PLUGIN_FIXTURES[:acl][:code], PLUGIN_FIXTURES[:acl][:sig])
409
+
410
+ scout(@client.key) # to write the initial history file. Sinatra MUST be running
411
+ $continue_streaming = true # so the streamer will run once
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
414
+
415
+ assert res.is_a?(Hash)
416
+ assert res[:plugins].is_a?(Array)
417
+ assert_equal 4, res[:plugins].size
418
+ assert_equal 2, res[:plugins][0][:fields][:load]
419
+ assert_equal 1, res[:plugins][1][:fields][:value]
420
+ assert_equal 2, res[:plugins][2][:fields][:value]
421
+ assert_equal 1, res[:plugins][3][:fields][:value]
422
+ end # end of mock_pusher
423
+ end
424
+
425
+ def test_streamer_with_local_plugin
426
+ local_path=File.join(AGENT_DIR,"my_local_plugin.rb")
427
+ code=<<-EOC
428
+ class LocalPluginTest < Scout::Plugin
429
+ def build_report; report(:answer=>42);end
410
430
  end
411
- end
412
- plugins=[]
413
- acl_code="class AclPlugin < Scout::Plugin;def build_report; report(:value=>1);end;end"
414
- acl_sig=<<EOS
415
- QT/IYlR+/3h0YwBAHJeFz4HRFlisocVGorafNYJSYJC5RaUKqxu3dM+bOU4P
416
- mQ5SmAt1mtXD5BJy2MeHam7Y8HAiWJbDBB318feZrC6xI2amu1b1/YMUyY8y
417
- fMXS9z8J+ABsFIyV26av1KLxU1EHxi9iKxPwMg0HKJhTBStX4uIyncr/+ZSS
418
- QKywEwPIPihFFyh9B2Z5WVSHtGcZG9CXDa20hrbQoNutOTniTkr00evBItYL
419
- FN4L0F0ApIjTTkZW2vjzNR59j8HfZ7zrPfy33VhJkyAS0o9nQt5v0J5wKHj1
420
- c3egj/Ffn/zSWZ1cTf3VSpfrGKUAlyB9KphZeYv2Og==
421
- EOS
422
- plugins << create_plugin(@client, "AclPlugin_1", acl_code, acl_sig)
423
-
424
- code="class XYZPlugin < Scout::Plugin;def build_report; report(:value=>2);end;end"
425
- sig=<<EOS
426
- 6cNcDCM2GWcoT1Iqri+XFPgAiMxQaf0b8kOi4KKafNVD94cPkcy6OknNeQUM
427
- v6GYcfGCAsiZvnjl/2wsqjvrAl/zyuSW/s5YLsjxca1LEvhkyxbpnDGuj32k
428
- 3IuWKQ6JuEbmPXPP1aFsosOm7dbTCrjEn1fDQWAzmfCwznHV3MiqzvPD2D9g
429
- 7gtxXcblNP6hm7A6AlBzP0hwYORR//gpLLGtmT5ewltHUj9aSUY0GQle3lvH
430
- /uzBDoV1x6mEYR2jPO5QQxL3BvTBvpC06ec8M/ZWbO9IwA7/DOs+vYfngxlp
431
- jbtpAK9QCaAalKy/Z29os/7aViHy9z9IVCpC/z3MDA==
432
- EOS
433
- plugins << create_plugin(@client, "XYZ Plugin", code, sig)
434
-
435
- plugins << create_plugin(@client, "AclPlugin_2", acl_code, acl_sig)
436
-
437
- scout(@client.key) # to write the initial history file. Sinatra MUST be running
438
- $continue_streaming = true # so the streamer will run once
439
- 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)
440
- res = $streamer_data # $streamer_data is set in the Channel.trigger! method we temporarily defined above
431
+ EOC
432
+ File.open(local_path,"w"){|f|f.write(code)}
433
+ scout(@client.key)
441
434
 
442
- assert res.is_a?(Hash)
443
- assert res[:plugins].is_a?(Array)
444
- assert_equal 4, res[:plugins].size
445
- assert_equal 2, res[:plugins][0][:fields][:load]
446
- assert_equal 1, res[:plugins][1][:fields][:value]
447
- assert_equal 2, res[:plugins][2][:fields][:value]
448
- assert_equal 1, res[:plugins][3][:fields][:value]
435
+ mock_pusher do
436
+ $continue_streaming = true # so the streamer will run once
437
+ 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
449
439
 
450
- Pusher::Channel.module_eval do
451
- alias trigger! orig_trigger!
452
- end
440
+ assert res.is_a?(Hash)
441
+ assert res[:plugins].is_a?(Array)
442
+ assert_equal 1, res[:plugins].size
443
+ assert_equal 2, res[:plugins][0][:fields][:load]
444
+ end # end of mock_pusher
453
445
  end
454
446
 
447
+
455
448
  # test streamer starting and stopping
456
449
  def test_streamer_process_management
457
450
  streamer_pid_file = File.join(AGENT_DIR, "scout_streamer.pid")
@@ -460,13 +453,14 @@ EOS
460
453
 
461
454
  assert !File.exist?(streamer_pid_file)
462
455
 
463
- assert @client.update_attribute(:streamer_command, "start,abc,1,3")
456
+ assert @client.update_attribute(:streamer_command, "start,A0000000000123,1,3")
464
457
  scout(@client.key)
465
458
  assert File.exist?(streamer_pid_file)
466
459
  process_id = File.read(streamer_pid_file).to_i
467
460
  assert process_running?(process_id)
468
461
  assert_nil @client.reload.streamer_command
469
462
 
463
+ sleep 2
470
464
  assert @client.update_attribute(:streamer_command, "stop")
471
465
  scout(@client.key)
472
466
  assert !File.exist?(streamer_pid_file)
@@ -578,7 +572,7 @@ EOS
578
572
  end
579
573
  end
580
574
 
581
- # see scout's rake plugin:sign task to create the signatre
575
+ # see scout's rake plugin:sign task to create the signature
582
576
  def create_plugin(client,name, code, signature)
583
577
  p=client.plugins.create(:name=>name)
584
578
  PluginMeta.create(:plugin=>p)
@@ -591,6 +585,49 @@ EOS
591
585
  p
592
586
  end
593
587
 
588
+ # this with a block to mock the pusher call. You can access the streamer data through the global $streamer_data
589
+ # Must be called with a code block
590
+ def mock_pusher
591
+ # redefine the trigger! method, so the streamer doesn't loop indefinitely. We can't just mock it, because
592
+ # we need to set the $continue_streaming=false
593
+ Pusher::Channel.module_eval do
594
+ alias orig_trigger! trigger!
595
+ def trigger!(event_name, data, socket=nil)
596
+ $streamer_data = data
597
+ $continue_streaming=false
598
+ end
599
+ end
600
+ yield # must be called with a block
601
+ Pusher::Channel.module_eval do
602
+ alias trigger! orig_trigger!
603
+ end
604
+ end
605
+
606
+
607
+ # Use these to create plugins as needed
608
+ PLUGIN_FIXTURES={
609
+ :acl=>{:code=>"class AclPlugin < Scout::Plugin;def build_report; report(:value=>1);end;end",
610
+ :sig=><<EOS
611
+ QT/IYlR+/3h0YwBAHJeFz4HRFlisocVGorafNYJSYJC5RaUKqxu3dM+bOU4P
612
+ mQ5SmAt1mtXD5BJy2MeHam7Y8HAiWJbDBB318feZrC6xI2amu1b1/YMUyY8y
613
+ fMXS9z8J+ABsFIyV26av1KLxU1EHxi9iKxPwMg0HKJhTBStX4uIyncr/+ZSS
614
+ QKywEwPIPihFFyh9B2Z5WVSHtGcZG9CXDa20hrbQoNutOTniTkr00evBItYL
615
+ FN4L0F0ApIjTTkZW2vjzNR59j8HfZ7zrPfy33VhJkyAS0o9nQt5v0J5wKHj1
616
+ c3egj/Ffn/zSWZ1cTf3VSpfrGKUAlyB9KphZeYv2Og==
617
+ EOS
618
+ },
619
+ :xyz=>{:code=>"class XYZPlugin < Scout::Plugin;def build_report; report(:value=>2);end;end",
620
+ :sig=><<EOS
621
+ 6cNcDCM2GWcoT1Iqri+XFPgAiMxQaf0b8kOi4KKafNVD94cPkcy6OknNeQUM
622
+ v6GYcfGCAsiZvnjl/2wsqjvrAl/zyuSW/s5YLsjxca1LEvhkyxbpnDGuj32k
623
+ 3IuWKQ6JuEbmPXPP1aFsosOm7dbTCrjEn1fDQWAzmfCwznHV3MiqzvPD2D9g
624
+ 7gtxXcblNP6hm7A6AlBzP0hwYORR//gpLLGtmT5ewltHUj9aSUY0GQle3lvH
625
+ /uzBDoV1x6mEYR2jPO5QQxL3BvTBvpC06ec8M/ZWbO9IwA7/DOs+vYfngxlp
626
+ jbtpAK9QCaAalKy/Z29os/7aViHy9z9IVCpC/z3MDA==
627
+ EOS
628
+ }
629
+ } # end of PLUGIN_FIXTURES
630
+
594
631
  end
595
632
 
596
633
  # Connect to AR before running
metadata CHANGED
@@ -1,39 +1,40 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: scout
3
- version: !ruby/object:Gem::Version
4
- version: 5.4.4.alpha
5
- prerelease: 6
3
+ version: !ruby/object:Gem::Version
4
+ version: 5.4.5.alpha
6
5
  platform: ruby
7
- authors:
6
+ authors:
8
7
  - Andre Lewis
9
8
  - Derek Haynes
10
9
  - James Edward Gray II
11
10
  autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2011-12-09 00:00:00.000000000 Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
13
+
14
+ date: 2011-12-13 00:00:00 -08:00
15
+ default_executable:
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
17
18
  name: elif
18
- requirement: &70156034409200 !ruby/object:Gem::Requirement
19
- none: false
20
- requirements:
21
- - - ! '>='
22
- - !ruby/object:Gem::Version
23
- version: '0'
24
19
  type: :runtime
25
- prerelease: false
26
- version_requirements: *70156034409200
27
- description: ! 'Scout makes monitoring and reporting on your web applications as flexible
28
- and simple as possible.
20
+ version_requirement:
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: "0"
26
+ version:
27
+ description: |
28
+ Scout makes monitoring and reporting on your web applications as flexible and simple as possible.
29
29
 
30
- '
31
30
  email: support@scoutapp.com
32
- executables:
31
+ executables:
33
32
  - scout
34
33
  extensions: []
34
+
35
35
  extra_rdoc_files: []
36
- files:
36
+
37
+ files:
37
38
  - .gitignore
38
39
  - CHANGELOG
39
40
  - Gemfile
@@ -219,31 +220,34 @@ files:
219
220
  - vendor/signature/spec/signature_spec.rb
220
221
  - vendor/signature/spec/spec_helper.rb
221
222
  - vendor/util/lib/core_extensions.rb
223
+ has_rdoc: true
222
224
  homepage: http://scoutapp.com
223
225
  licenses: []
226
+
224
227
  post_install_message:
225
228
  rdoc_options: []
226
- require_paths:
229
+
230
+ require_paths:
227
231
  - lib
228
- required_ruby_version: !ruby/object:Gem::Requirement
229
- none: false
230
- requirements:
231
- - - ! '>='
232
- - !ruby/object:Gem::Version
233
- version: '0'
234
- required_rubygems_version: !ruby/object:Gem::Requirement
235
- none: false
236
- requirements:
237
- - - ! '>'
238
- - !ruby/object:Gem::Version
232
+ required_ruby_version: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: "0"
237
+ version:
238
+ required_rubygems_version: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - ">"
241
+ - !ruby/object:Gem::Version
239
242
  version: 1.3.1
243
+ version:
240
244
  requirements: []
245
+
241
246
  rubyforge_project: scout
242
- rubygems_version: 1.8.10
247
+ rubygems_version: 1.3.5
243
248
  signing_key:
244
249
  specification_version: 3
245
- summary: Web-based monitoring, reporting, and alerting for your servers, clusters,
246
- and applications.
247
- test_files:
250
+ summary: Web-based monitoring, reporting, and alerting for your servers, clusters, and applications.
251
+ test_files:
248
252
  - test/plugins/disk_usage.rb
249
253
  - test/scout_test.rb