RailsRemoteControl 1.0.0
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/History.txt +7 -0
- data/LICENSE.txt +27 -0
- data/Manifest.txt +21 -0
- data/README.txt +38 -0
- data/Rakefile +23 -0
- data/bin/rails_remote_control +6 -0
- data/lib/rails_remote_control.rb +64 -0
- data/lib/rails_remote_control/http_server.rb +68 -0
- data/lib/rails_remote_control/process.rb +59 -0
- data/lib/rails_remote_control/remote.rb +38 -0
- data/lib/rails_remote_control/remote/server.rb +16 -0
- data/lib/rails_remote_control/server.rb +117 -0
- data/lib/rails_remote_control/servlet.rb +207 -0
- data/test/test_rails_remote_control.rb +0 -0
- data/test/test_rails_remote_control_http_server.rb +16 -0
- data/test/test_rails_remote_control_process.rb +93 -0
- data/test/test_rails_remote_control_remote.rb +42 -0
- data/test/test_rails_remote_control_remote_server.rb +17 -0
- data/test/test_rails_remote_control_server.rb +80 -0
- data/test/test_rails_remote_control_servlet.rb +230 -0
- data/test/util.rb +39 -0
- metadata +107 -0
data/History.txt
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright 2006 Eric Hodel, The Robot Co-op. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
11
|
+
documentation and/or other materials provided with the distribution.
|
12
|
+
3. Neither the names of the authors nor the names of their contributors
|
13
|
+
may be used to endorse or promote products derived from this software
|
14
|
+
without specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
17
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
20
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
21
|
+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
22
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
23
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
24
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
25
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
|
data/Manifest.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
History.txt
|
2
|
+
LICENSE.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
Rakefile
|
6
|
+
bin/rails_remote_control
|
7
|
+
lib/rails_remote_control.rb
|
8
|
+
lib/rails_remote_control/http_server.rb
|
9
|
+
lib/rails_remote_control/process.rb
|
10
|
+
lib/rails_remote_control/remote.rb
|
11
|
+
lib/rails_remote_control/remote/server.rb
|
12
|
+
lib/rails_remote_control/server.rb
|
13
|
+
lib/rails_remote_control/servlet.rb
|
14
|
+
test/test_rails_remote_control.rb
|
15
|
+
test/test_rails_remote_control_http_server.rb
|
16
|
+
test/test_rails_remote_control_process.rb
|
17
|
+
test/test_rails_remote_control_remote.rb
|
18
|
+
test/test_rails_remote_control_remote_server.rb
|
19
|
+
test/test_rails_remote_control_server.rb
|
20
|
+
test/test_rails_remote_control_servlet.rb
|
21
|
+
test/util.rb
|
data/README.txt
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
RailsRemoteControl by Eric Hodel <drbrain@segment7.net>
|
2
|
+
|
3
|
+
http://seattlerb.rubyforge.org/RailsRemoteControl
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Rails Remote Control allows you to attach to running Rails processes
|
8
|
+
using DRb and change the log level without restarts. Also, view
|
9
|
+
actions handled per process.
|
10
|
+
|
11
|
+
== FEATURES/PROBLEMS:
|
12
|
+
|
13
|
+
* Monitor processes
|
14
|
+
* Control process log level without restarts
|
15
|
+
* Logs actions handled and count per process
|
16
|
+
|
17
|
+
== SYNOPSYS:
|
18
|
+
|
19
|
+
See RailsRemoteControl:
|
20
|
+
|
21
|
+
ri RailsRemoteControl
|
22
|
+
|
23
|
+
== REQUIREMENTS:
|
24
|
+
|
25
|
+
* A Rails project
|
26
|
+
* DRb connectivity
|
27
|
+
* RingyDingy (gem)
|
28
|
+
|
29
|
+
== INSTALL:
|
30
|
+
|
31
|
+
First install the gem:
|
32
|
+
|
33
|
+
$ sudo gem install RailsRemoteControl
|
34
|
+
|
35
|
+
Then read and follow the RailsRemoteControl installation instructions:
|
36
|
+
|
37
|
+
$ ri RailsRemoteControl
|
38
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
$:.unshift 'lib'
|
7
|
+
require 'rails_remote_control'
|
8
|
+
|
9
|
+
hoe = Hoe.new('RailsRemoteControl', RailsRemoteControl::VERSION) do |p|
|
10
|
+
p.summary = 'Alter Rails log levels and monitor processes without restarts'
|
11
|
+
p.description = File.read('README.txt').scan(/== DESCRIPTION:(.*?)==/m).first.first.strip
|
12
|
+
p.author = 'Eric Hodel'
|
13
|
+
p.email = 'drbrain@segment7.net'
|
14
|
+
p.rubyforge_name = 'seattlerb'
|
15
|
+
p.url = 'http://seattlerb.rubyforge.org/RailsRemoteControl'
|
16
|
+
p.changes = File.read('History.txt').scan(/\A(=.*?)(=|\Z)/m).first.first
|
17
|
+
|
18
|
+
p.extra_deps << ['RingyDingy', '>= 1.2.0']
|
19
|
+
p.extra_deps << ['ZenTest', '>= 3.4.2']
|
20
|
+
p.extra_deps << ['actionpack', '>= 1.12.5']
|
21
|
+
end
|
22
|
+
|
23
|
+
# vim: syntax=Ruby
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
##
|
4
|
+
# RailsRemoteControl allows you to monitor individual Rails processes and
|
5
|
+
# adjust the log level of a process for debugging purposes. (For example, to
|
6
|
+
# turn on partial rendering times for a single process.)
|
7
|
+
#
|
8
|
+
# = Installation
|
9
|
+
#
|
10
|
+
# First, start a RailsRemoteControl::Server when your Rails process starts up
|
11
|
+
# by adding these two lines to config/environment.rb:
|
12
|
+
#
|
13
|
+
# require 'rails_remote_control/server'
|
14
|
+
# RailsRemoteControl::Server.run 'my_rails_app'
|
15
|
+
#
|
16
|
+
# Next, add <tt>include RailsRemoteControl::Process</tt> in Application
|
17
|
+
# controller:
|
18
|
+
#
|
19
|
+
# require 'rails_remote_control/process'
|
20
|
+
#
|
21
|
+
# class ApplicationController < ActionController::Base
|
22
|
+
#
|
23
|
+
# include RailsRemoteControl::Process
|
24
|
+
#
|
25
|
+
# # ...
|
26
|
+
#
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# = Usage
|
30
|
+
#
|
31
|
+
# Then start up a RingServer where you want to monitor and control your remote
|
32
|
+
# processes:
|
33
|
+
#
|
34
|
+
# $ ring_server -d
|
35
|
+
#
|
36
|
+
# You can start the RingServer up before or after the Rails app. The rails
|
37
|
+
# processes will automatically connect soon after it starts.
|
38
|
+
#
|
39
|
+
# Then start up the RailsRemoteControl::HTTPServer so you can control your
|
40
|
+
# processes:
|
41
|
+
#
|
42
|
+
# $ rails_remote_control -d
|
43
|
+
#
|
44
|
+
# Then connect with your web browser to port 8000 on that machine.
|
45
|
+
#
|
46
|
+
# = It Doesn't Work
|
47
|
+
#
|
48
|
+
# * Do you have forward and reverse DNS set up for all your machines?
|
49
|
+
# $ host `hostname`
|
50
|
+
# ziz.jijo.segment7.net has address 10.101.28.1
|
51
|
+
# $ host 10.101.28.1
|
52
|
+
# 1.28.101.10.in-addr.arpa domain name pointer ziz.jijo.segment7.net.
|
53
|
+
# Both forward and reverse addresses need to match here.
|
54
|
+
# * Have you disabled IPv6 or set up RDNS for your IPv6 hosts?
|
55
|
+
|
56
|
+
module RailsRemoteControl
|
57
|
+
|
58
|
+
##
|
59
|
+
# The version of RailsRemoteControl you have installed.
|
60
|
+
|
61
|
+
VERSION = '1.0.0'
|
62
|
+
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'rails_remote_control'
|
2
|
+
require 'rails_remote_control/servlet'
|
3
|
+
require 'webrick/httpserver'
|
4
|
+
|
5
|
+
##
|
6
|
+
# RailsRemoteControl HTTP server.
|
7
|
+
#
|
8
|
+
# This provides the console for monitoring and modifying your Rails processes.
|
9
|
+
# By default it runs on port 8000.
|
10
|
+
|
11
|
+
class RailsRemoteControl::HTTPServer < WEBrick::HTTPServer
|
12
|
+
|
13
|
+
@server = nil
|
14
|
+
|
15
|
+
##
|
16
|
+
# Processes ARGV style +args+ into an options Hash.
|
17
|
+
|
18
|
+
def self.process_args(args)
|
19
|
+
options = {}
|
20
|
+
options[:Daemon] = false
|
21
|
+
options[:Port] = 8000
|
22
|
+
|
23
|
+
opts = OptionParser.new do |opts|
|
24
|
+
opts.banner = "Usage: #{name} [options]"
|
25
|
+
opts.on("-p", "--port=PORT",
|
26
|
+
"RailsRemoteControl HTTP Server Port", Integer) do |port|
|
27
|
+
options[:Port] = port
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-d", "--daemon",
|
31
|
+
"Run as a daemon process") do |daemon|
|
32
|
+
options[:Daemon] = true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.parse! args
|
37
|
+
|
38
|
+
return options
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Start and run a RailsRemoteControl HTTP server, depending upon +args+.
|
43
|
+
|
44
|
+
def self.run(args = ARGV)
|
45
|
+
options = process_args args
|
46
|
+
|
47
|
+
if options[:Daemon] then
|
48
|
+
WEBrick::Daemon.start
|
49
|
+
end
|
50
|
+
|
51
|
+
@server = new :Port => options[:Port]
|
52
|
+
@server.mount '/', RailsRemoteControl::Servlet
|
53
|
+
|
54
|
+
trap 'INT' do stop end
|
55
|
+
trap 'KILL' do stop end
|
56
|
+
|
57
|
+
@server.start
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Stop the RailsRemoteControl HTTP server.
|
62
|
+
|
63
|
+
def self.stop
|
64
|
+
@server.stop
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rails_remote_control'
|
2
|
+
|
3
|
+
##
|
4
|
+
# RailsRemoteControl::Process records statistics of a running Rails process.
|
5
|
+
#
|
6
|
+
# Include it in your ApplicationController to record these statistics:
|
7
|
+
#
|
8
|
+
# require 'rails_remote_control/process'
|
9
|
+
#
|
10
|
+
# class ApplicationController < ActionController::Base
|
11
|
+
#
|
12
|
+
# include RailsRemoteControl::Process
|
13
|
+
#
|
14
|
+
# end
|
15
|
+
|
16
|
+
module RailsRemoteControl::Process
|
17
|
+
|
18
|
+
@requests_attempted = 0
|
19
|
+
@requests_handled = 0
|
20
|
+
|
21
|
+
@requests = Hash.new { |h,full_action_name| h[full_action_name] = 0 }
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
##
|
26
|
+
# Hash mapping action names to times handled.
|
27
|
+
|
28
|
+
attr_reader :requests
|
29
|
+
|
30
|
+
##
|
31
|
+
# Requests attempted
|
32
|
+
|
33
|
+
attr_accessor :requests_attempted
|
34
|
+
|
35
|
+
##
|
36
|
+
# Requests successfully handled
|
37
|
+
|
38
|
+
attr_accessor :requests_handled
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# ActionController::Base#process wrapper that records statistics for actions
|
44
|
+
# handled by this Rails process.
|
45
|
+
|
46
|
+
def process(req, res)
|
47
|
+
RailsRemoteControl::Process.requests_attempted += 1
|
48
|
+
|
49
|
+
result = super
|
50
|
+
|
51
|
+
RailsRemoteControl::Process.requests_handled += 1
|
52
|
+
full_action_name = "#{self.class.name}##{action_name}"
|
53
|
+
RailsRemoteControl::Process.requests[full_action_name] += 1
|
54
|
+
|
55
|
+
return result
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rails_remote_control'
|
2
|
+
require 'ringy_dingy/ring_server'
|
3
|
+
require 'rails_remote_control/server'
|
4
|
+
|
5
|
+
##
|
6
|
+
# RailsRemoteControl process locater.
|
7
|
+
|
8
|
+
class RailsRemoteControl::Remote
|
9
|
+
|
10
|
+
##
|
11
|
+
# Remote server struct
|
12
|
+
|
13
|
+
Server = Struct.new :host, :pid, :remote_server
|
14
|
+
|
15
|
+
##
|
16
|
+
# Looks for services on the RingServer and returns an Array of discovered
|
17
|
+
# Rails processes.
|
18
|
+
|
19
|
+
def services
|
20
|
+
services = RingyDingy::RingServer.list_services
|
21
|
+
return [] if services.empty?
|
22
|
+
|
23
|
+
services = RingyDingy::RingServer.list_services.values.first.uniq
|
24
|
+
|
25
|
+
rrc_servers = services.select do |_, klass,|
|
26
|
+
klass == RailsRemoteControl::Server::RINGY_DINGY_SERVICE
|
27
|
+
end
|
28
|
+
|
29
|
+
rrc_servers.map do |_, _, server, name|
|
30
|
+
host, pid, = name.split '_', 3
|
31
|
+
Server.new host, pid.to_i, server
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'rails_remote_control/remote/server'
|
38
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rails_remote_control/remote'
|
2
|
+
|
3
|
+
##
|
4
|
+
# RailsRemoteControl remote server convenience wrapper.
|
5
|
+
|
6
|
+
class RailsRemoteControl::Remote::Server
|
7
|
+
|
8
|
+
##
|
9
|
+
# Dispatch other messages to the remote server.
|
10
|
+
|
11
|
+
def method_missing(*args, &block)
|
12
|
+
remote_server.send(*args, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'logger'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'ringy_dingy'
|
5
|
+
require 'rails_remote_control'
|
6
|
+
require 'rails_remote_control/process'
|
7
|
+
|
8
|
+
##
|
9
|
+
# RailsRemoteControl server process. Run this from config/environment.rb to
|
10
|
+
# allow RailsRemoteControl::Remote to find the Rails processes you are
|
11
|
+
# running.
|
12
|
+
#
|
13
|
+
# = Example
|
14
|
+
#
|
15
|
+
# Add the following lines to config/environment.rb for your application:
|
16
|
+
#
|
17
|
+
# require 'rails_remote_control/server'
|
18
|
+
# RailsRemoteControl::Server.run 'my_rails_app'
|
19
|
+
|
20
|
+
class RailsRemoteControl::Server
|
21
|
+
|
22
|
+
##
|
23
|
+
# Service name for RingyDingy
|
24
|
+
|
25
|
+
RINGY_DINGY_SERVICE = name.delete(':').intern
|
26
|
+
|
27
|
+
##
|
28
|
+
# Run as +name+.
|
29
|
+
|
30
|
+
def self.run(name = nil)
|
31
|
+
new(name).run
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Creates a new RailsRemoteControl server as +name+.
|
36
|
+
#
|
37
|
+
# Use +name+ to disambiguate multiple Rails applications.
|
38
|
+
|
39
|
+
def initialize(name)
|
40
|
+
@name = name
|
41
|
+
@ringy_dingy = RingyDingy.new self, RINGY_DINGY_SERVICE, name
|
42
|
+
@pid = $PID
|
43
|
+
@host = Socket.gethostname
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Start running
|
48
|
+
|
49
|
+
def run
|
50
|
+
@ringy_dingy.run
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Returns the current log level of the default logger for this Rails
|
55
|
+
# process.
|
56
|
+
|
57
|
+
def log_level
|
58
|
+
RAILS_DEFAULT_LOGGER.level
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Sets the current log level of the default logger for this Rails process to
|
63
|
+
# +level+.
|
64
|
+
|
65
|
+
def log_level=(level)
|
66
|
+
RAILS_DEFAULT_LOGGER.level = level
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# A Hash mapping action names to number of requests handled.
|
71
|
+
#
|
72
|
+
# See RailsRemoteControl::Process#requests.
|
73
|
+
|
74
|
+
def requests
|
75
|
+
RailsRemoteControl::Process.requests
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Number of requests attempted by this Rails process.
|
80
|
+
|
81
|
+
def requests_attempted
|
82
|
+
RailsRemoteControl::Process.requests_attempted
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Number of requests handled by this Rails process. (If this number is
|
87
|
+
# different from #requests_attempted something bad happened, check your
|
88
|
+
# logs.)
|
89
|
+
|
90
|
+
def requests_handled
|
91
|
+
RailsRemoteControl::Process.requests_handled
|
92
|
+
end
|
93
|
+
|
94
|
+
def ==(other) # :nodoc:
|
95
|
+
self.class === other and other.name == self.name and
|
96
|
+
other.host == self.host and other.pid == self.pid
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
|
101
|
+
##
|
102
|
+
# Name of this Rails process.
|
103
|
+
|
104
|
+
attr_reader :name
|
105
|
+
|
106
|
+
##
|
107
|
+
# Host this Rails process is running on.
|
108
|
+
|
109
|
+
attr_reader :host
|
110
|
+
|
111
|
+
##
|
112
|
+
# Process id for this Rails process.
|
113
|
+
|
114
|
+
attr_reader :pid
|
115
|
+
|
116
|
+
end
|
117
|
+
|
@@ -0,0 +1,207 @@
|
|
1
|
+
$TESTING = false unless defined? $TESTING
|
2
|
+
|
3
|
+
require 'webrick/httpservlet/abstract'
|
4
|
+
require 'webrick/httpstatus'
|
5
|
+
require 'rails_remote_control'
|
6
|
+
require 'rails_remote_control/remote'
|
7
|
+
require 'logger'
|
8
|
+
|
9
|
+
##
|
10
|
+
# RailsRemoteControl WEBrick servlet for process monitoring and control.
|
11
|
+
|
12
|
+
class RailsRemoteControl::Servlet < WEBrick::HTTPServlet::AbstractServlet
|
13
|
+
|
14
|
+
logger_levels = Logger::Severity.constants.map do |c|
|
15
|
+
[Logger::Severity.const_get(c), c]
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Map Logger's log levels to friendly names
|
20
|
+
|
21
|
+
LOGGER_LEVELS = logger_levels.sort_by { |l,n| l }
|
22
|
+
|
23
|
+
@services = nil
|
24
|
+
@services_thread = nil
|
25
|
+
|
26
|
+
##
|
27
|
+
# Accessor for services cache
|
28
|
+
|
29
|
+
def self.services
|
30
|
+
@services
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Fetching a list of services will block for five seconds, so do that in a
|
35
|
+
# separate thread and cache the results. This method is called at require
|
36
|
+
# time.
|
37
|
+
|
38
|
+
def self.start_services_thread
|
39
|
+
@services_thread = Thread.start do
|
40
|
+
remote = RailsRemoteControl::Remote.new
|
41
|
+
|
42
|
+
loop do
|
43
|
+
@services = remote.services
|
44
|
+
sleep 10
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
sleep 0.1 while @services.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
start_services_thread unless $TESTING
|
52
|
+
|
53
|
+
def do_GET(req, res) # :nodoc:
|
54
|
+
case req.request_uri.request_uri
|
55
|
+
when '/' then
|
56
|
+
res.body = list
|
57
|
+
when %r%\A/server/([^/]+)/(\d+)\Z%
|
58
|
+
res.body = server $1, $2.to_i
|
59
|
+
else
|
60
|
+
super
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def do_POST(req, res) # :nodoc:
|
65
|
+
case req.request_uri.request_uri
|
66
|
+
when %r%\A/server/([^/]+)/(\d+)/log_level\Z%
|
67
|
+
host, pid = $1, $2.to_i
|
68
|
+
req.body =~ /log_level=(\d+)/
|
69
|
+
level = Integer($1) rescue nil
|
70
|
+
res.body = set_log_level host, pid, level
|
71
|
+
else
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Displays a list of rails processes available for remote control.
|
78
|
+
|
79
|
+
def list
|
80
|
+
out = "<title>No Processes</title>\n"
|
81
|
+
out << "<h1>No Processes</h1>\n"
|
82
|
+
out << "<p>Did you start ring_server?"
|
83
|
+
out << "<p>Did you start rails_remote_control?\n"
|
84
|
+
out << "<p>Did you set up your Rails application for monitoring?\n"
|
85
|
+
return out if services.nil?
|
86
|
+
|
87
|
+
out = []
|
88
|
+
out << "<title>Active Processes</title>"
|
89
|
+
out << "<h1>Active Processes</h1>"
|
90
|
+
out << nil
|
91
|
+
out << '<table>'
|
92
|
+
out << '<tr><th colspan=2> <th colspan=2>Requests<th> '
|
93
|
+
out << '<tr><th>Host<th>Process<th>Attempted<th>Handled<th>Log Level'
|
94
|
+
|
95
|
+
services.each do |server|
|
96
|
+
row = server_row server
|
97
|
+
out << row if row
|
98
|
+
end
|
99
|
+
|
100
|
+
out << '</table>' << nil
|
101
|
+
|
102
|
+
out.join "\n"
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Displays information about process +pid+ on +host+.
|
107
|
+
|
108
|
+
def server(host, pid)
|
109
|
+
server = get_server host, pid
|
110
|
+
|
111
|
+
out = []
|
112
|
+
out << "<title>#{host} pid #{pid}</title>"
|
113
|
+
out << "<h1>#{host} pid #{pid}</h1>"
|
114
|
+
out << nil
|
115
|
+
|
116
|
+
out << '<a href="/">Active Processes</a>'
|
117
|
+
out << nil
|
118
|
+
|
119
|
+
out << '<table>'
|
120
|
+
out << "<tr><th>Log Level<td>#{server.log_level}"
|
121
|
+
out << "<tr><th>Requests Attempted<td>#{server.requests_attempted}"
|
122
|
+
out << "<tr><th>Requests Handled<td>#{server.requests_handled}"
|
123
|
+
out << '</table>' << nil
|
124
|
+
|
125
|
+
out << "<form method=\"post\" action=\"/server/#{host}/#{pid}/log_level\">"
|
126
|
+
out << '<div>'
|
127
|
+
out << '<label for="log_level">Change Log Level</label>'
|
128
|
+
out << '<select id="log_level" name="log_level">'
|
129
|
+
|
130
|
+
LOGGER_LEVELS.each do |level, name|
|
131
|
+
selected = server.log_level == level ? ' selected' : nil
|
132
|
+
out << "<option#{selected} value=\"#{level}\">#{name}</option>"
|
133
|
+
end
|
134
|
+
|
135
|
+
out << '</select>'
|
136
|
+
out << '<input type="submit" value="Change">'
|
137
|
+
out << '</div>' << '</form>' << nil
|
138
|
+
|
139
|
+
unless server.requests.empty? then
|
140
|
+
out << '<table>'
|
141
|
+
out << "<tr><th>Action<th>Requests Handled"
|
142
|
+
server.requests.sort_by { |a,c| -c }.each do |action, count|
|
143
|
+
out << "<tr><td>#{action}<td>#{count}"
|
144
|
+
end
|
145
|
+
out << '</table>' << nil
|
146
|
+
end
|
147
|
+
|
148
|
+
out.join "\n"
|
149
|
+
rescue DRb::DRbConnError
|
150
|
+
raise WEBrick::HTTPStatus::NotFound, "#{host}:#{pid} is no longer reachable"
|
151
|
+
rescue NoMethodError
|
152
|
+
raise WEBrick::HTTPStatus::NotFound, "#{host}:#{pid} has gone away"
|
153
|
+
end
|
154
|
+
|
155
|
+
def service(req, res) # :nodoc:
|
156
|
+
@req = req
|
157
|
+
@res = res
|
158
|
+
@res.content_type = 'text/html'
|
159
|
+
super
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Services accessor
|
164
|
+
|
165
|
+
def services
|
166
|
+
self.class.services
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Construct a table row with information on +server+.
|
171
|
+
|
172
|
+
def server_row(server)
|
173
|
+
tr = []
|
174
|
+
tr << "<td>#{server.host}"
|
175
|
+
tr << "<td><a href=\"/server/#{server.host}/#{server.pid}\">#{server.pid}</a>"
|
176
|
+
tr << "<td>#{server.requests_attempted}"
|
177
|
+
tr << "<td>#{server.requests_handled}"
|
178
|
+
tr << "<td>#{server.log_level}"
|
179
|
+
|
180
|
+
"<tr>#{tr.join}"
|
181
|
+
|
182
|
+
rescue DRb::DRbConnError
|
183
|
+
nil
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Sets the log level for process +pid+ on +host+ to +level+.
|
188
|
+
|
189
|
+
def set_log_level(host, pid, level)
|
190
|
+
server = get_server host, pid
|
191
|
+
server.log_level = level
|
192
|
+
@res.set_redirect WEBrick::HTTPStatus::SeeOther, "/server/#{host}/#{pid}"
|
193
|
+
rescue DRb::DRbConnError
|
194
|
+
raise WEBrick::HTTPStatus::NotFound, "#{host}:#{pid} is no longer reachable"
|
195
|
+
rescue NoMethodError
|
196
|
+
raise WEBrick::HTTPStatus::NotFound, "#{host}:#{pid} has gone away"
|
197
|
+
end
|
198
|
+
|
199
|
+
##
|
200
|
+
# Retrieves the server for process +pid+ on +host+.
|
201
|
+
|
202
|
+
def get_server(host, pid)
|
203
|
+
services.find { |s| s.host == host and s.pid == pid }
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$TESTING = true
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rails_remote_control/http_server'
|
5
|
+
|
6
|
+
class TestRailsRemoteControlHTTPServer < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_self_process_args
|
9
|
+
options = RailsRemoteControl::HTTPServer.process_args %w[-d -p 80]
|
10
|
+
|
11
|
+
expected = { :Daemon => true, :Port => 80 }
|
12
|
+
assert_equal expected, options
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
module ActionController; end
|
4
|
+
class ActionController::Base
|
5
|
+
|
6
|
+
attr_reader :action_name
|
7
|
+
|
8
|
+
def self.process(req, res)
|
9
|
+
new.process req, res
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(req, res)
|
13
|
+
params = req.parameters
|
14
|
+
@action_name = params['action']
|
15
|
+
end
|
16
|
+
|
17
|
+
def controller_class_name
|
18
|
+
self.class.name.split('::').last
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rails_remote_control/process'
|
24
|
+
|
25
|
+
class ApplicationController < ActionController::Base
|
26
|
+
include RailsRemoteControl::Process
|
27
|
+
end
|
28
|
+
|
29
|
+
class MyController < ApplicationController
|
30
|
+
|
31
|
+
def index
|
32
|
+
end
|
33
|
+
|
34
|
+
def show
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
module Nested; end
|
40
|
+
class Nested::MyController < ApplicationController
|
41
|
+
|
42
|
+
def index
|
43
|
+
end
|
44
|
+
|
45
|
+
def show
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
module RailsRemoteControl
|
51
|
+
def Process.reset
|
52
|
+
@requests_handled = 0
|
53
|
+
@requests_attempted = 0
|
54
|
+
@requests.clear
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class TestRailsRemoteControlProcess < Test::Unit::TestCase
|
59
|
+
|
60
|
+
RRCP = RailsRemoteControl::Process
|
61
|
+
|
62
|
+
FakeRequest = Struct.new :parameters
|
63
|
+
|
64
|
+
def setup
|
65
|
+
@request = FakeRequest.new
|
66
|
+
@request.parameters = { 'action' => 'index' }
|
67
|
+
end
|
68
|
+
|
69
|
+
def teardown
|
70
|
+
RRCP.reset
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_process
|
74
|
+
MyController.new.process @request, nil
|
75
|
+
|
76
|
+
assert_equal 1, RRCP.requests_handled
|
77
|
+
assert_equal 1, RRCP.requests_attempted
|
78
|
+
|
79
|
+
expected = { 'MyController#index' => 1 }
|
80
|
+
assert_equal expected, RRCP.requests
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_process_nested
|
84
|
+
Nested::MyController.new.process @request, nil
|
85
|
+
|
86
|
+
assert_equal 1, RRCP.requests_handled
|
87
|
+
|
88
|
+
expected = { 'Nested::MyController#index' => 1 }
|
89
|
+
assert_equal expected, RRCP.requests
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
$TESTING = true
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rails_remote_control/remote'
|
5
|
+
require 'test/util'
|
6
|
+
|
7
|
+
class TestRailsRemoteControlRemote < Test::Unit::TestCase
|
8
|
+
|
9
|
+
RRCR = RailsRemoteControl::Remote
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@remote = RRCR.new
|
13
|
+
RingyDingy::RingServer.default = RingyDingy::RingServer::DEFAULT
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
RingyDingy::RingServer.default = RingyDingy::RingServer::DEFAULT
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_services
|
21
|
+
RingyDingy::RingServer.default = RingyDingy::RingServer::DEFAULT
|
22
|
+
|
23
|
+
expected = [
|
24
|
+
RRCR::Server.new('cutie', 1000,
|
25
|
+
RailsRemoteControl::Server.new('43places')),
|
26
|
+
RRCR::Server.new('cutie', 1001,
|
27
|
+
RailsRemoteControl::Server.new('43places')),
|
28
|
+
RRCR::Server.new('hal', 61000,
|
29
|
+
RailsRemoteControl::Server.new('43things')),
|
30
|
+
]
|
31
|
+
|
32
|
+
assert_equal expected, @remote.services
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_services_no_services
|
36
|
+
RingyDingy::RingServer.default = {}
|
37
|
+
|
38
|
+
assert_equal [], @remote.services
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rails_remote_control/server'
|
3
|
+
require 'rails_remote_control/remote/server'
|
4
|
+
|
5
|
+
class TestRailsRemoteControlRemoteServer < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@server = RailsRemoteControl::Server.new 'name'
|
9
|
+
@remote_server = RailsRemoteControl::Remote::Server.new 'localhost', $$, @server
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_method_missing
|
13
|
+
assert_equal 0, @remote_server.requests_handled
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'test/zentest_assertions'
|
4
|
+
require 'test/util'
|
5
|
+
|
6
|
+
require 'rails_remote_control/server'
|
7
|
+
|
8
|
+
class RailsRemoteControl::Server
|
9
|
+
attr_reader :ringy_dingy
|
10
|
+
public :host, :name, :pid
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestRailsRemoteControlServer < Test::Unit::TestCase
|
14
|
+
|
15
|
+
RRCS = RailsRemoteControl::Server
|
16
|
+
|
17
|
+
def setup
|
18
|
+
@name = 'RailsRemoteControl::Server test'
|
19
|
+
@server = RRCS.new @name
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_equal
|
23
|
+
server = RRCS.new @name
|
24
|
+
|
25
|
+
assert_equal server, @server
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_host
|
29
|
+
assert_equal Socket.gethostname, @server.host
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_initialize
|
33
|
+
deny_nil @server.ringy_dingy
|
34
|
+
assert_equal "#{Socket.gethostname.downcase}_#{$PID}_#{@name}",
|
35
|
+
@server.ringy_dingy.identifier
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_log_level
|
39
|
+
assert_equal Logger::DEBUG, @server.log_level
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_log_level_equals
|
43
|
+
level = @server.log_level
|
44
|
+
@server.log_level = Logger::FATAL
|
45
|
+
assert_equal Logger::FATAL, @server.log_level
|
46
|
+
assert_equal Logger::FATAL, RAILS_DEFAULT_LOGGER.level
|
47
|
+
ensure
|
48
|
+
@server.log_level = level
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_name
|
52
|
+
assert_equal @name, @server.name
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_pid
|
56
|
+
assert_equal $$, @server.pid
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_requests
|
60
|
+
assert_equal Hash.new, @server.requests
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_requests_attempted
|
64
|
+
assert_equal 0, @server.requests_attempted
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_requests_handled
|
68
|
+
assert_equal 0, @server.requests_handled
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_run
|
72
|
+
assert_nil @server.ringy_dingy.thread
|
73
|
+
@server.run
|
74
|
+
deny_nil @server.ringy_dingy.thread
|
75
|
+
end
|
76
|
+
|
77
|
+
alias deny_nil assert_not_nil # HACK ZenTest 3.4.2
|
78
|
+
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,230 @@
|
|
1
|
+
$TESTING = true
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'stringio'
|
5
|
+
require 'test/util'
|
6
|
+
|
7
|
+
require 'rails_remote_control/servlet'
|
8
|
+
|
9
|
+
require 'webrick/httprequest'
|
10
|
+
require 'webrick/httpresponse'
|
11
|
+
|
12
|
+
class FakeWEBrickServer
|
13
|
+
def [](arg); end
|
14
|
+
end
|
15
|
+
|
16
|
+
class RailsRemoteControl::Servlet
|
17
|
+
def self.services=(services)
|
18
|
+
@services = services
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class TestRailsRemoteControlServlet < Test::Unit::TestCase
|
23
|
+
|
24
|
+
RRCRS = RailsRemoteControl::Remote::Server
|
25
|
+
RRCS = RailsRemoteControl::Servlet
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@server = RailsRemoteControl::Server.new 'name'
|
29
|
+
@dead_server = RailsRemoteControl::Server.new 'name'
|
30
|
+
def @dead_server.requests_attempted() raise DRb::DRbConnError; end
|
31
|
+
RRCS.services = [
|
32
|
+
RRCRS.new('cutie', 1000, @server),
|
33
|
+
RRCRS.new('cutie', 1001, @server),
|
34
|
+
RRCRS.new('hal', 61000, @server),
|
35
|
+
RRCRS.new('hal', 61001, @dead_server),
|
36
|
+
]
|
37
|
+
|
38
|
+
@http_server = FakeWEBrickServer.new
|
39
|
+
@servlet = RRCS.new @http_server
|
40
|
+
@config = { :Logger => nil, :HTTPVersion => '1.0' }
|
41
|
+
end
|
42
|
+
|
43
|
+
def teardown
|
44
|
+
RailsRemoteControl::Server.new(nil).requests.clear
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_do_GET_list
|
48
|
+
req = WEBrick::HTTPRequest.new @config
|
49
|
+
req.parse StringIO.new("GET / HTTP/1.0\r\n\r\n")
|
50
|
+
res = WEBrick::HTTPResponse.new @config
|
51
|
+
|
52
|
+
def @servlet.list
|
53
|
+
return 'list'
|
54
|
+
end
|
55
|
+
|
56
|
+
@servlet.service req, res
|
57
|
+
|
58
|
+
assert_equal 'list', res.body
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_do_GET_server
|
62
|
+
req = WEBrick::HTTPRequest.new @config
|
63
|
+
req.parse StringIO.new("GET /server/cutie/1000 HTTP/1.0\r\n\r\n")
|
64
|
+
res = WEBrick::HTTPResponse.new @config
|
65
|
+
|
66
|
+
def @servlet.server(host, pid)
|
67
|
+
return "server #{host} #{pid}"
|
68
|
+
end
|
69
|
+
|
70
|
+
@servlet.service req, res
|
71
|
+
|
72
|
+
assert_equal 'server cutie 1000', res.body
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_do_GET_server_with_dot
|
76
|
+
req = WEBrick::HTTPRequest.new @config
|
77
|
+
req.parse StringIO.new("GET /server/kaa.local/1000 HTTP/1.0\r\n\r\n")
|
78
|
+
res = WEBrick::HTTPResponse.new @config
|
79
|
+
|
80
|
+
def @servlet.server(host, pid)
|
81
|
+
return "server %p %p" % [host, pid]
|
82
|
+
end
|
83
|
+
|
84
|
+
@servlet.service req, res
|
85
|
+
|
86
|
+
assert_equal 'server "kaa.local" 1000', res.body
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_do_POST_server_log_level
|
90
|
+
req = WEBrick::HTTPRequest.new @config
|
91
|
+
req.parse StringIO.new("POST /server/cutie/1000/log_level HTTP/1.0\r\nContent-Length: 11\r\n\r\nlog_level=5")
|
92
|
+
res = WEBrick::HTTPResponse.new @config
|
93
|
+
|
94
|
+
def @servlet.set_log_level(host, pid, level)
|
95
|
+
return "server #{host} #{pid} #{level}"
|
96
|
+
end
|
97
|
+
|
98
|
+
@servlet.service req, res
|
99
|
+
|
100
|
+
assert_equal 'server cutie 1000 5', res.body
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_list
|
104
|
+
expected = <<-EOF
|
105
|
+
<title>Active Processes</title>
|
106
|
+
<h1>Active Processes</h1>
|
107
|
+
|
108
|
+
<table>
|
109
|
+
<tr><th colspan=2> <th colspan=2>Requests<th>
|
110
|
+
<tr><th>Host<th>Process<th>Attempted<th>Handled<th>Log Level
|
111
|
+
<tr><td>cutie<td><a href="/server/cutie/1000">1000</a><td>0<td>0<td>0
|
112
|
+
<tr><td>cutie<td><a href="/server/cutie/1001">1001</a><td>0<td>0<td>0
|
113
|
+
<tr><td>hal<td><a href="/server/hal/61000">61000</a><td>0<td>0<td>0
|
114
|
+
</table>
|
115
|
+
EOF
|
116
|
+
|
117
|
+
assert_equal expected, @servlet.list
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_server
|
121
|
+
server = RailsRemoteControl::Server.new 'name'
|
122
|
+
server.requests['RouteController#index'] = 2
|
123
|
+
server.requests['RouteController#route_markers'] = 1
|
124
|
+
RRCS.services = [RRCRS.new('cutie', 1000, server)]
|
125
|
+
|
126
|
+
expected = <<-EOF
|
127
|
+
<title>cutie pid 1000</title>
|
128
|
+
<h1>cutie pid 1000</h1>
|
129
|
+
|
130
|
+
<a href="/">Active Processes</a>
|
131
|
+
|
132
|
+
<table>
|
133
|
+
<tr><th>Log Level<td>0
|
134
|
+
<tr><th>Requests Attempted<td>0
|
135
|
+
<tr><th>Requests Handled<td>0
|
136
|
+
</table>
|
137
|
+
|
138
|
+
<form method="post" action="/server/cutie/1000/log_level">
|
139
|
+
<div>
|
140
|
+
<label for="log_level">Change Log Level</label>
|
141
|
+
<select id="log_level" name="log_level">
|
142
|
+
<option selected value="0">DEBUG</option>
|
143
|
+
<option value="1">INFO</option>
|
144
|
+
<option value="2">WARN</option>
|
145
|
+
<option value="3">ERROR</option>
|
146
|
+
<option value="4">FATAL</option>
|
147
|
+
<option value="5">UNKNOWN</option>
|
148
|
+
</select>
|
149
|
+
<input type="submit" value="Change">
|
150
|
+
</div>
|
151
|
+
</form>
|
152
|
+
|
153
|
+
<table>
|
154
|
+
<tr><th>Action<th>Requests Handled
|
155
|
+
<tr><td>RouteController#index<td>2
|
156
|
+
<tr><td>RouteController#route_markers<td>1
|
157
|
+
</table>
|
158
|
+
EOF
|
159
|
+
|
160
|
+
assert_equal expected, @servlet.server('cutie', 1000)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_server_dead
|
164
|
+
e = assert_raise WEBrick::HTTPStatus::NotFound do
|
165
|
+
@servlet.server 'hal', 61001
|
166
|
+
end
|
167
|
+
|
168
|
+
assert_equal 'hal:61001 is no longer reachable', e.message
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_server_gone
|
172
|
+
util_test_gone :server
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_server_no_requests
|
176
|
+
expected = <<-EOF
|
177
|
+
<title>cutie pid 1001</title>
|
178
|
+
<h1>cutie pid 1001</h1>
|
179
|
+
|
180
|
+
<a href="/">Active Processes</a>
|
181
|
+
|
182
|
+
<table>
|
183
|
+
<tr><th>Log Level<td>0
|
184
|
+
<tr><th>Requests Attempted<td>0
|
185
|
+
<tr><th>Requests Handled<td>0
|
186
|
+
</table>
|
187
|
+
|
188
|
+
<form method="post" action="/server/cutie/1001/log_level">
|
189
|
+
<div>
|
190
|
+
<label for="log_level">Change Log Level</label>
|
191
|
+
<select id="log_level" name="log_level">
|
192
|
+
<option selected value="0">DEBUG</option>
|
193
|
+
<option value="1">INFO</option>
|
194
|
+
<option value="2">WARN</option>
|
195
|
+
<option value="3">ERROR</option>
|
196
|
+
<option value="4">FATAL</option>
|
197
|
+
<option value="5">UNKNOWN</option>
|
198
|
+
</select>
|
199
|
+
<input type="submit" value="Change">
|
200
|
+
</div>
|
201
|
+
</form>
|
202
|
+
EOF
|
203
|
+
|
204
|
+
assert_equal expected, @servlet.server('cutie', 1001)
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_set_log_level
|
208
|
+
@servlet.instance_variable_set :@res, WEBrick::HTTPResponse.new(@config)
|
209
|
+
|
210
|
+
assert_raise WEBrick::HTTPStatus::SeeOther do
|
211
|
+
@servlet.set_log_level 'cutie', 1000, 5
|
212
|
+
end
|
213
|
+
|
214
|
+
assert_equal 5, @server.log_level
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_set_log_level_no_server
|
218
|
+
util_test_gone :set_log_level, 5
|
219
|
+
end
|
220
|
+
|
221
|
+
def util_test_gone(action, *args)
|
222
|
+
e = assert_raise WEBrick::HTTPStatus::NotFound do
|
223
|
+
@servlet.send(action, 'none', 0, *args)
|
224
|
+
end
|
225
|
+
|
226
|
+
assert_equal 'none:0 has gone away', e.message
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
data/test/util.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'test/zentest_assertions'
|
4
|
+
require 'ringy_dingy/ring_server'
|
5
|
+
require 'rails_remote_control/server'
|
6
|
+
|
7
|
+
RAILS_DEFAULT_LOGGER = Logger.new '/dev/null'
|
8
|
+
|
9
|
+
class RingyDingy::RingServer
|
10
|
+
|
11
|
+
@s1 = RailsRemoteControl::Server.new '43places'
|
12
|
+
@s2 = RailsRemoteControl::Server.new '43places'
|
13
|
+
@s3 = RailsRemoteControl::Server.new '43things'
|
14
|
+
|
15
|
+
DEFAULT = {
|
16
|
+
'druby://localhost:10000' => [
|
17
|
+
[:name, RailsRemoteControl::Server::RINGY_DINGY_SERVICE, @s1,
|
18
|
+
'cutie_1000_43places'],
|
19
|
+
[:name, RailsRemoteControl::Server::RINGY_DINGY_SERVICE, @s2,
|
20
|
+
'cutie_1001_43places'],
|
21
|
+
[:name, RailsRemoteControl::Server::RINGY_DINGY_SERVICE, @s3,
|
22
|
+
'hal_61000_43places'],
|
23
|
+
]
|
24
|
+
}
|
25
|
+
|
26
|
+
def self.default=(default)
|
27
|
+
@default = default
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
remove_method :list_services
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.list_services
|
35
|
+
@default
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0.8
|
3
|
+
specification_version: 1
|
4
|
+
name: RailsRemoteControl
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2007-01-02 00:00:00 -08:00
|
8
|
+
summary: Alter Rails log levels and monitor processes without restarts
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: drbrain@segment7.net
|
12
|
+
homepage: http://seattlerb.rubyforge.org/RailsRemoteControl
|
13
|
+
rubyforge_project: seattlerb
|
14
|
+
description: Rails Remote Control allows you to attach to running Rails processes using DRb and change the log level without restarts. Also, view actions handled per process.
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Eric Hodel
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- LICENSE.txt
|
34
|
+
- Manifest.txt
|
35
|
+
- README.txt
|
36
|
+
- Rakefile
|
37
|
+
- bin/rails_remote_control
|
38
|
+
- lib/rails_remote_control.rb
|
39
|
+
- lib/rails_remote_control/http_server.rb
|
40
|
+
- lib/rails_remote_control/process.rb
|
41
|
+
- lib/rails_remote_control/remote.rb
|
42
|
+
- lib/rails_remote_control/remote/server.rb
|
43
|
+
- lib/rails_remote_control/server.rb
|
44
|
+
- lib/rails_remote_control/servlet.rb
|
45
|
+
- test/test_rails_remote_control.rb
|
46
|
+
- test/test_rails_remote_control_http_server.rb
|
47
|
+
- test/test_rails_remote_control_process.rb
|
48
|
+
- test/test_rails_remote_control_remote.rb
|
49
|
+
- test/test_rails_remote_control_remote_server.rb
|
50
|
+
- test/test_rails_remote_control_server.rb
|
51
|
+
- test/test_rails_remote_control_servlet.rb
|
52
|
+
- test/util.rb
|
53
|
+
test_files:
|
54
|
+
- test/test_rails_remote_control.rb
|
55
|
+
- test/test_rails_remote_control_http_server.rb
|
56
|
+
- test/test_rails_remote_control_process.rb
|
57
|
+
- test/test_rails_remote_control_remote.rb
|
58
|
+
- test/test_rails_remote_control_remote_server.rb
|
59
|
+
- test/test_rails_remote_control_server.rb
|
60
|
+
- test/test_rails_remote_control_servlet.rb
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
extra_rdoc_files: []
|
64
|
+
|
65
|
+
executables:
|
66
|
+
- rails_remote_control
|
67
|
+
extensions: []
|
68
|
+
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
dependencies:
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: hoe
|
74
|
+
version_requirement:
|
75
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.1.6
|
80
|
+
version:
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: RingyDingy
|
83
|
+
version_requirement:
|
84
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.2.0
|
89
|
+
version:
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: ZenTest
|
92
|
+
version_requirement:
|
93
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 3.4.2
|
98
|
+
version:
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: actionpack
|
101
|
+
version_requirement:
|
102
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.12.5
|
107
|
+
version:
|