scout 5.3.5 → 5.4.4.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/CHANGELOG +0 -12
- data/Gemfile +4 -0
- data/README +8 -0
- data/Rakefile +6 -108
- data/bin/scout +1 -0
- data/lib/scout.rb +5 -4
- data/lib/scout/command.rb +11 -12
- data/lib/scout/command/install.rb +1 -1
- data/lib/scout/command/run.rb +13 -1
- data/lib/scout/command/sign.rb +2 -8
- data/lib/scout/command/stream.rb +50 -0
- data/lib/scout/command/test.rb +1 -1
- data/lib/scout/daemon_spawn.rb +215 -0
- data/lib/scout/plugin.rb +20 -1
- data/lib/scout/server.rb +16 -111
- data/lib/scout/server_base.rb +100 -0
- data/lib/scout/streamer.rb +162 -0
- data/lib/scout/streamer_control.rb +43 -0
- data/lib/scout/version.rb +3 -0
- data/scout.gemspec +27 -0
- data/test/plugins/disk_usage.rb +86 -0
- data/test/scout_test.rb +598 -0
- data/vendor/pusher-gem/Gemfile +2 -0
- data/vendor/pusher-gem/LICENSE +20 -0
- data/vendor/pusher-gem/README.md +80 -0
- data/vendor/pusher-gem/Rakefile +11 -0
- data/vendor/pusher-gem/examples/async_message.rb +28 -0
- data/vendor/pusher-gem/lib/pusher.rb +107 -0
- data/vendor/pusher-gem/lib/pusher/channel.rb +154 -0
- data/vendor/pusher-gem/lib/pusher/request.rb +107 -0
- data/vendor/pusher-gem/pusher.gemspec +28 -0
- data/vendor/pusher-gem/spec/channel_spec.rb +274 -0
- data/vendor/pusher-gem/spec/pusher_spec.rb +87 -0
- data/vendor/pusher-gem/spec/spec_helper.rb +13 -0
- data/vendor/ruby-hmac/History.txt +15 -0
- data/vendor/ruby-hmac/Manifest.txt +11 -0
- data/vendor/ruby-hmac/README.md +41 -0
- data/vendor/ruby-hmac/Rakefile +23 -0
- data/vendor/ruby-hmac/lib/hmac-md5.rb +11 -0
- data/vendor/ruby-hmac/lib/hmac-rmd160.rb +11 -0
- data/vendor/ruby-hmac/lib/hmac-sha1.rb +11 -0
- data/vendor/ruby-hmac/lib/hmac-sha2.rb +25 -0
- data/vendor/ruby-hmac/lib/hmac.rb +118 -0
- data/vendor/ruby-hmac/lib/ruby_hmac.rb +2 -0
- data/vendor/ruby-hmac/ruby-hmac.gemspec +33 -0
- data/vendor/ruby-hmac/test/test_hmac.rb +89 -0
- data/vendor/signature/.document +5 -0
- data/vendor/signature/.gitignore +21 -0
- data/vendor/signature/Gemfile +3 -0
- data/vendor/signature/Gemfile.lock +29 -0
- data/vendor/signature/LICENSE +20 -0
- data/vendor/signature/README.md +55 -0
- data/vendor/signature/Rakefile +2 -0
- data/vendor/signature/VERSION +1 -0
- data/vendor/signature/lib/signature.rb +142 -0
- data/vendor/signature/lib/signature/version.rb +3 -0
- data/vendor/signature/signature.gemspec +22 -0
- data/vendor/signature/spec/signature_spec.rb +176 -0
- data/vendor/signature/spec/spec_helper.rb +10 -0
- data/vendor/util/lib/core_extensions.rb +60 -0
- metadata +120 -84
- data/AUTHORS +0 -4
- data/COPYING +0 -340
- data/INSTALL +0 -18
- data/TODO +0 -6
data/lib/scout/plugin.rb
CHANGED
@@ -49,6 +49,16 @@ module Scout
|
|
49
49
|
code =~ EMBEDDED_OPTIONS_REGEX
|
50
50
|
return $2
|
51
51
|
end
|
52
|
+
|
53
|
+
def extract_code_class(code)
|
54
|
+
match = /class\s\b(\w*)\s+?<\s+Scout::Plugin/.match(code)
|
55
|
+
|
56
|
+
if match
|
57
|
+
return match[1]
|
58
|
+
else
|
59
|
+
raise ArgumentError, "can't identify plugin class"
|
60
|
+
end
|
61
|
+
end
|
52
62
|
end
|
53
63
|
|
54
64
|
# Creates a new Scout Plugin to run.
|
@@ -122,7 +132,16 @@ module Scout
|
|
122
132
|
alias_method :add_#{kind}, :#{kind}
|
123
133
|
END
|
124
134
|
end
|
125
|
-
|
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
|
+
|
126
145
|
#
|
127
146
|
# Usage:
|
128
147
|
#
|
data/lib/scout/server.rb
CHANGED
@@ -1,29 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require "timeout"
|
7
|
-
require "stringio"
|
8
|
-
require "zlib"
|
9
|
-
require "socket"
|
10
|
-
require "base64"
|
11
|
-
|
12
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), *%w[.. .. vendor json_pure lib])
|
1
|
+
|
2
|
+
Dir.glob(File.join(File.dirname(__FILE__), *%w[.. .. vendor *])).each do |dir|
|
3
|
+
$LOAD_PATH << File.join(dir,"lib")
|
4
|
+
end
|
5
|
+
|
13
6
|
require "json"
|
7
|
+
require "pusher"
|
14
8
|
|
15
9
|
module Scout
|
16
|
-
class Server
|
17
|
-
# A new class for plugin Timeout errors.
|
18
|
-
class PluginTimeoutError < RuntimeError; end
|
19
|
-
# A new class for API Timeout errors.
|
20
|
-
class APITimeoutError < RuntimeError; end
|
21
|
-
|
22
|
-
# Headers passed up with all API requests.
|
23
|
-
HTTP_HEADERS = { "Client-Version" => Scout::VERSION,
|
24
|
-
"Client-Hostname" => Socket.gethostname,
|
25
|
-
"Accept-Encoding" => "gzip" }
|
26
|
-
|
10
|
+
class Server < Scout::ServerBase
|
27
11
|
#
|
28
12
|
# A plugin cannot take more than DEFAULT_PLUGIN_TIMEOUT seconds to execute,
|
29
13
|
# otherwise, a timeout error is generated. This can be overriden by
|
@@ -39,20 +23,20 @@ module Scout
|
|
39
23
|
attr_reader :new_plan
|
40
24
|
attr_reader :directives
|
41
25
|
attr_reader :plugin_config
|
26
|
+
attr_reader :streamer_command
|
42
27
|
|
43
28
|
# Creates a new Scout Server connection.
|
44
|
-
def initialize(server, client_key, history_file, logger = nil, server_name=nil
|
29
|
+
def initialize(server, client_key, history_file, logger = nil, server_name=nil)
|
45
30
|
@server = server
|
46
31
|
@client_key = client_key
|
47
32
|
@history_file = history_file
|
48
33
|
@history = Hash.new
|
49
34
|
@logger = logger
|
50
35
|
@server_name = server_name
|
51
|
-
@http_proxy = http_proxy
|
52
|
-
@https_proxy = https_proxy
|
53
36
|
@plugin_plan = []
|
54
37
|
@plugins_with_signature_errors = []
|
55
38
|
@directives = {} # take_snapshots, interval, sleep_interval
|
39
|
+
@streamer_command = nil
|
56
40
|
@new_plan = false
|
57
41
|
@local_plugin_path = File.dirname(history_file) # just put overrides and ad-hoc plugins in same directory as history file.
|
58
42
|
@plugin_config_path = File.join(@local_plugin_path, "plugins.properties")
|
@@ -68,6 +52,7 @@ module Scout
|
|
68
52
|
end
|
69
53
|
|
70
54
|
def refresh?
|
55
|
+
#info "called refresh: ping_key=#{ping_key}"
|
71
56
|
return true if !ping_key or account_public_key_changed? # fetch the plan again if the account key is modified/created
|
72
57
|
|
73
58
|
url=URI.join( @server.sub("https://","http://"), "/clients/#{ping_key}/ping.scout")
|
@@ -77,6 +62,8 @@ module Scout
|
|
77
62
|
headers["If-Modified-Since"] = @history["plan_last_modified"]
|
78
63
|
end
|
79
64
|
get(url, "Could not ping #{url} for refresh info", headers) do |res|
|
65
|
+
info "inside 'refresh?' #{res.to_hash.to_json}"
|
66
|
+
@streamer_command = res["x-streamer-command"] # usually will be nil, but can be [start,abcd,1234,5678|stop]
|
80
67
|
if res.is_a?(Net::HTTPNotModified)
|
81
68
|
return false
|
82
69
|
else
|
@@ -107,7 +94,6 @@ module Scout
|
|
107
94
|
if res["Content-Encoding"] == "gzip" and body and not body.empty?
|
108
95
|
body = Zlib::GzipReader.new(StringIO.new(body)).read
|
109
96
|
end
|
110
|
-
|
111
97
|
body_as_hash = JSON.parse(body)
|
112
98
|
|
113
99
|
temp_plugins=Array(body_as_hash["plugins"])
|
@@ -152,7 +138,6 @@ module Scout
|
|
152
138
|
|
153
139
|
@new_plan = true # used in determination if we should checkin this time or not
|
154
140
|
|
155
|
-
|
156
141
|
# Add local plugins to the plan.
|
157
142
|
@plugin_plan += get_local_plugins
|
158
143
|
rescue Exception =>e
|
@@ -165,6 +150,7 @@ module Scout
|
|
165
150
|
@plugin_plan = Array(@history["old_plugins"])
|
166
151
|
@plugin_plan += get_local_plugins
|
167
152
|
@directives = @history["directives"] || Hash.new
|
153
|
+
|
168
154
|
end
|
169
155
|
@plugin_plan.reject! { |p| p['code'].nil? }
|
170
156
|
end
|
@@ -245,7 +231,7 @@ module Scout
|
|
245
231
|
def time_to_checkin?
|
246
232
|
@history['last_checkin'] == nil ||
|
247
233
|
@directives['interval'] == nil ||
|
248
|
-
(Time.now.to_i - Time.at(@history['last_checkin']).to_i).abs+15
|
234
|
+
(Time.now.to_i - Time.at(@history['last_checkin']).to_i).abs+15 > @directives['interval'].to_i*60
|
249
235
|
rescue
|
250
236
|
debug "Failed to calculate time_to_checkin. @history['last_checkin']=#{@history['last_checkin']}. "+
|
251
237
|
"@directives['interval']=#{@directives['interval']}. Time.now.to_i=#{Time.now.to_i}"
|
@@ -495,7 +481,7 @@ module Scout
|
|
495
481
|
contents=File.read(@history_file)
|
496
482
|
begin
|
497
483
|
@history = YAML.load(contents)
|
498
|
-
rescue
|
484
|
+
rescue => e
|
499
485
|
backup_path=File.join(File.dirname(@history_file), "history.corrupt")
|
500
486
|
info "Couldn't parse the history file. Deleting it and resetting to an empty history file. Keeping a backup at #{backup_path}"
|
501
487
|
File.open(backup_path,"w"){|f|f.write contents}
|
@@ -540,70 +526,6 @@ module Scout
|
|
540
526
|
}
|
541
527
|
end
|
542
528
|
|
543
|
-
def urlify(url_name, options = Hash.new)
|
544
|
-
return unless @server
|
545
|
-
options.merge!(:client_version => Scout::VERSION)
|
546
|
-
URI.join( @server,
|
547
|
-
"/clients/CLIENT_KEY/#{url_name}.scout".
|
548
|
-
gsub(/\bCLIENT_KEY\b/, @client_key).
|
549
|
-
gsub(/\b[A-Z_]+\b/) { |k| options[k.downcase.to_sym] || k } )
|
550
|
-
end
|
551
|
-
|
552
|
-
def post(url, error, body, headers = Hash.new, &response_handler)
|
553
|
-
return unless url
|
554
|
-
request(url, response_handler, error) do |connection|
|
555
|
-
post = Net::HTTP::Post.new( url.path +
|
556
|
-
(url.query ? ('?' + url.query) : ''),
|
557
|
-
HTTP_HEADERS.merge(headers) )
|
558
|
-
post.body = body
|
559
|
-
connection.request(post)
|
560
|
-
end
|
561
|
-
end
|
562
|
-
|
563
|
-
def get(url, error, headers = Hash.new, &response_handler)
|
564
|
-
return unless url
|
565
|
-
request(url, response_handler, error) do |connection|
|
566
|
-
connection.get( url.path + (url.query ? ('?' + url.query) : ''),
|
567
|
-
HTTP_HEADERS.merge(headers) )
|
568
|
-
end
|
569
|
-
end
|
570
|
-
|
571
|
-
def request(url, response_handler, error, &connector)
|
572
|
-
response = nil
|
573
|
-
Timeout.timeout(5 * 60, APITimeoutError) do
|
574
|
-
|
575
|
-
# take care of http/https proxy, if specified in command line options
|
576
|
-
# Given a blank string, the proxy_uri URI instance's host/port/user/pass will be nil
|
577
|
-
# Net::HTTP::Proxy returns a regular Net::HTTP class if the first argument (host) is nil
|
578
|
-
proxy_uri = URI.parse(url.is_a?(URI::HTTPS) ? @https_proxy : @http_proxy)
|
579
|
-
http=Net::HTTP::Proxy(proxy_uri.host,proxy_uri.port,proxy_uri.user,proxy_uri.port).new(url.host, url.port)
|
580
|
-
|
581
|
-
if url.is_a? URI::HTTPS
|
582
|
-
http.use_ssl = true
|
583
|
-
http.ca_file = File.join( File.dirname(__FILE__),
|
584
|
-
*%w[.. .. data cacert.pem] )
|
585
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER |
|
586
|
-
OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
587
|
-
end
|
588
|
-
response = no_warnings { http.start(&connector) }
|
589
|
-
end
|
590
|
-
case response
|
591
|
-
when Net::HTTPSuccess, Net::HTTPNotModified
|
592
|
-
response_handler[response] unless response_handler.nil?
|
593
|
-
else
|
594
|
-
error = "Server says: #{response['x-scout-msg']}" if response['x-scout-msg']
|
595
|
-
fatal error
|
596
|
-
raise SystemExit.new(error)
|
597
|
-
end
|
598
|
-
rescue Timeout::Error
|
599
|
-
fatal "Request timed out."
|
600
|
-
exit
|
601
|
-
rescue Exception
|
602
|
-
raise if $!.is_a? SystemExit
|
603
|
-
fatal "An HTTP error occurred: #{$!.message}"
|
604
|
-
exit
|
605
|
-
end
|
606
|
-
|
607
529
|
def checkin
|
608
530
|
debug """
|
609
531
|
#{PP.pp(@checkin, '')}
|
@@ -626,23 +548,6 @@ module Scout
|
|
626
548
|
end
|
627
549
|
|
628
550
|
|
629
|
-
def no_warnings
|
630
|
-
old_verbose = $VERBOSE
|
631
|
-
$VERBOSE = false
|
632
|
-
yield
|
633
|
-
ensure
|
634
|
-
$VERBOSE = old_verbose
|
635
|
-
end
|
636
|
-
|
637
|
-
# Forward Logger methods to an active instance, when there is one.
|
638
|
-
def method_missing(meth, *args, &block)
|
639
|
-
if (Logger::SEV_LABEL - %w[ANY]).include? meth.to_s.upcase
|
640
|
-
@logger.send(meth, *args, &block) unless @logger.nil?
|
641
|
-
else
|
642
|
-
super
|
643
|
-
end
|
644
|
-
end
|
645
|
-
|
646
551
|
private
|
647
552
|
|
648
553
|
# Called during initialization; loads the plugin_configs (local plugin configurations for passwords, etc)
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require "net/https"
|
2
|
+
require "uri"
|
3
|
+
require "yaml"
|
4
|
+
require "timeout"
|
5
|
+
require "stringio"
|
6
|
+
require "zlib"
|
7
|
+
require "socket"
|
8
|
+
require "base64"
|
9
|
+
|
10
|
+
module Scout
|
11
|
+
class ServerBase
|
12
|
+
# A new class for plugin Timeout errors.
|
13
|
+
class PluginTimeoutError < RuntimeError; end
|
14
|
+
# A new class for API Timeout errors.
|
15
|
+
class APITimeoutError < RuntimeError; end
|
16
|
+
|
17
|
+
# Headers passed up with all API requests.
|
18
|
+
HTTP_HEADERS = { "Client-Version" => Scout::VERSION,
|
19
|
+
"Client-Hostname" => Socket.gethostname,
|
20
|
+
"Accept-Encoding" => "gzip" }
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def urlify(url_name, options = Hash.new)
|
26
|
+
return unless @server
|
27
|
+
options.merge!(:client_version => Scout::VERSION)
|
28
|
+
URI.join(@server,
|
29
|
+
"/clients/CLIENT_KEY/#{url_name}.scout".
|
30
|
+
gsub(/\bCLIENT_KEY\b/, @client_key).
|
31
|
+
gsub(/\b[A-Z_]+\b/) { |k| options[k.downcase.to_sym] || k })
|
32
|
+
end
|
33
|
+
|
34
|
+
def post(url, error, body, headers = Hash.new, &response_handler)
|
35
|
+
return unless url
|
36
|
+
request(url, response_handler, error) do |connection|
|
37
|
+
post = Net::HTTP::Post.new(url.path +
|
38
|
+
(url.query ? ('?' + url.query) : ''),
|
39
|
+
HTTP_HEADERS.merge(headers))
|
40
|
+
post.body = body
|
41
|
+
connection.request(post)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def get(url, error, headers = Hash.new, &response_handler)
|
46
|
+
return unless url
|
47
|
+
request(url, response_handler, error) do |connection|
|
48
|
+
connection.get(url.path + (url.query ? ('?' + url.query) : ''),
|
49
|
+
HTTP_HEADERS.merge(headers))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def request(url, response_handler, error, &connector)
|
54
|
+
response = nil
|
55
|
+
Timeout.timeout(5 * 60, APITimeoutError) do
|
56
|
+
http = Net::HTTP.new(url.host, url.port)
|
57
|
+
if url.is_a? URI::HTTPS
|
58
|
+
http.use_ssl = true
|
59
|
+
http.ca_file = File.join(File.dirname(__FILE__),
|
60
|
+
*%w[.. .. data cacert.pem])
|
61
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER |
|
62
|
+
OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
63
|
+
end
|
64
|
+
response = no_warnings { http.start(&connector) }
|
65
|
+
end
|
66
|
+
case response
|
67
|
+
when Net::HTTPSuccess, Net::HTTPNotModified
|
68
|
+
response_handler[response] unless response_handler.nil?
|
69
|
+
else
|
70
|
+
error = "Server says: #{response['x-scout-msg']}" if response['x-scout-msg']
|
71
|
+
fatal error
|
72
|
+
raise SystemExit.new(error)
|
73
|
+
end
|
74
|
+
rescue Timeout::Error
|
75
|
+
fatal "Request timed out."
|
76
|
+
exit
|
77
|
+
rescue Exception
|
78
|
+
raise if $!.is_a? SystemExit
|
79
|
+
fatal "An HTTP error occurred: #{$!.message}"
|
80
|
+
exit
|
81
|
+
end
|
82
|
+
|
83
|
+
def no_warnings
|
84
|
+
old_verbose = $VERBOSE
|
85
|
+
$VERBOSE = false
|
86
|
+
yield
|
87
|
+
ensure
|
88
|
+
$VERBOSE = old_verbose
|
89
|
+
end
|
90
|
+
|
91
|
+
# Forward Logger methods to an active instance, when there is one.
|
92
|
+
def method_missing(meth, *args, &block)
|
93
|
+
if (Logger::SEV_LABEL - %w[ANY]).include? meth.to_s.upcase
|
94
|
+
@logger.send(meth, *args, &block) unless @logger.nil?
|
95
|
+
else
|
96
|
+
super
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Scout
|
5
|
+
class Streamer < Scout::ServerBase
|
6
|
+
MAX_DURATION = 60*30 # will shut down automatically after this many seconds
|
7
|
+
SLEEP = 1
|
8
|
+
|
9
|
+
# * history_file is the *path* to the history file
|
10
|
+
# * plugin_ids is an array of integers
|
11
|
+
def initialize(server, client_key, history_file, plugin_ids, streaming_key, logger = nil)
|
12
|
+
@server = server
|
13
|
+
@client_key = client_key
|
14
|
+
@history_file = history_file
|
15
|
+
@history = Hash.new
|
16
|
+
@logger = logger
|
17
|
+
|
18
|
+
@plugins = []
|
19
|
+
|
20
|
+
Pusher.app_id = '11495'
|
21
|
+
Pusher.key = 'a95aa7293cd158100246'
|
22
|
+
Pusher.secret = '9c13ccfe325fe3ae682d'
|
23
|
+
|
24
|
+
debug "plugin_ids = #{plugin_ids.inspect}"
|
25
|
+
debug "streaming_key = #{streaming_key}"
|
26
|
+
|
27
|
+
streamer_start_time = Time.now
|
28
|
+
|
29
|
+
hostname=Socket.gethostname
|
30
|
+
# load history
|
31
|
+
load_history
|
32
|
+
|
33
|
+
# get the array of plugins, AKA the plugin plan
|
34
|
+
@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')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# main loop. Continue running until global $continue_streaming is set to false OR we've been running for MAX DURATION
|
47
|
+
while(streamer_start_time+MAX_DURATION > Time.now && $continue_streaming) do
|
48
|
+
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))
|
52
|
+
start_time=Time.now
|
53
|
+
plugin.reset!
|
54
|
+
plugin.run
|
55
|
+
duration=((Time.now-start_time)*1000).to_i
|
56
|
+
|
57
|
+
plugins << {:duration=>duration,
|
58
|
+
:fields=>plugin.reports.inject{|memo,hash|memo.merge(hash)},
|
59
|
+
:name=>@plugin_plan[i]["name"],
|
60
|
+
:id=>@plugin_plan[i]["id"]}
|
61
|
+
end
|
62
|
+
|
63
|
+
bundle={:hostname=>hostname,
|
64
|
+
:server_time=>Time.now.strftime("%I:%M:%S %p"),
|
65
|
+
:num_processes=>`ps -e | wc -l`.chomp.to_i,
|
66
|
+
:plugins=>plugins }
|
67
|
+
|
68
|
+
begin
|
69
|
+
Pusher[streaming_key].trigger!('server_data', bundle)
|
70
|
+
rescue Pusher::Error => e
|
71
|
+
# (Pusher::AuthenticationError, Pusher::HTTPError, or Pusher::Error)
|
72
|
+
error "Error pushing data: #{e.message}"
|
73
|
+
end
|
74
|
+
|
75
|
+
if false
|
76
|
+
# debugging
|
77
|
+
File.open(File.join(File.dirname(@history_file),"debug.txt"),"w") do |f|
|
78
|
+
f.puts "... sleeping @ #{Time.now.strftime("%I:%M:%S %p")}..."
|
79
|
+
f.puts bundle.to_yaml
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
sleep(SLEEP)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
private
|
89
|
+
|
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']
|
105
|
+
|
106
|
+
# take care of plugin overrides
|
107
|
+
local_path = File.join(File.dirname(@history_file), "#{plugin_id}.rb")
|
108
|
+
if File.exist?(local_path)
|
109
|
+
code_to_run = File.read(local_path)
|
110
|
+
else
|
111
|
+
code_to_run=plugin['code'] || ""
|
112
|
+
end
|
113
|
+
|
114
|
+
id_and_name = "#{plugin['id']}-#{plugin['name']}".sub(/\A-/, "")
|
115
|
+
last_run = @history["last_runs"][id_and_name] ||
|
116
|
+
@history["last_runs"][plugin['name']]
|
117
|
+
memory = @history["memory"][id_and_name] ||
|
118
|
+
@history["memory"][plugin['name']]
|
119
|
+
options=(plugin['options'] || Hash.new)
|
120
|
+
options.merge!(:tuner_days=>"")
|
121
|
+
code_class=Plugin.extract_code_class(code_to_run)
|
122
|
+
begin
|
123
|
+
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)
|
127
|
+
|
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
|
131
|
+
|
132
|
+
rescue Exception
|
133
|
+
error "Plugin would not compile: #{$!.message}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def load_history
|
139
|
+
begin
|
140
|
+
debug "Loading history file..."
|
141
|
+
contents=File.read(@history_file)
|
142
|
+
@history = YAML.load(contents)
|
143
|
+
rescue => e
|
144
|
+
info "Couldn't load or parse the history file at #{@history_file}. Exiting."
|
145
|
+
exit(1)
|
146
|
+
end
|
147
|
+
info "History file loaded."
|
148
|
+
end
|
149
|
+
|
150
|
+
# Forward Logger methods to an active instance, when there is one.
|
151
|
+
def method_missing(meth, *args, &block)
|
152
|
+
if (Logger::SEV_LABEL - %w[ANY]).include? meth.to_s.upcase
|
153
|
+
@logger.send(meth, *args, &block) unless @logger.nil?
|
154
|
+
else
|
155
|
+
super
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def growl(message)`growlnotify -m '#{message.gsub("'","\'")}'`;end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|