racknga 0.9.3 → 0.9.4

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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -12
  3. data/README.textile +9 -8
  4. data/Rakefile +19 -272
  5. data/doc/text/news.textile +8 -0
  6. data/lib/racknga/access_log_parser.rb +1 -1
  7. data/lib/racknga/api-keys.rb +40 -0
  8. data/lib/racknga/cache_database.rb +2 -2
  9. data/lib/racknga/exception_mail_notifier.rb +5 -5
  10. data/lib/racknga/log_database.rb +1 -1
  11. data/lib/racknga/log_entry.rb +1 -1
  12. data/lib/racknga/middleware/auth/api-key.rb +95 -0
  13. data/lib/racknga/middleware/cache.rb +20 -6
  14. data/lib/racknga/middleware/deflater.rb +1 -1
  15. data/lib/racknga/middleware/exception_notifier.rb +1 -1
  16. data/lib/racknga/middleware/instance_name.rb +65 -12
  17. data/lib/racknga/middleware/jsonp.rb +24 -5
  18. data/lib/racknga/middleware/log.rb +1 -1
  19. data/lib/racknga/middleware/nginx_raw_uri.rb +1 -1
  20. data/lib/racknga/middleware/range.rb +1 -1
  21. data/lib/racknga/reverse_line_reader.rb +1 -1
  22. data/lib/racknga/utils.rb +1 -1
  23. data/lib/racknga/version.rb +2 -2
  24. data/lib/racknga.rb +2 -1
  25. data/munin/plugins/passenger_application_ +61 -47
  26. data/munin/plugins/passenger_status +64 -33
  27. data/test/racknga-test-utils.rb +2 -1
  28. data/test/run-test.rb +1 -3
  29. data/test/test-access-log-parser.rb +1 -1
  30. data/test/test-api-keys.rb +80 -0
  31. data/test/test-middleware-auth-api-key.rb +144 -0
  32. data/test/test-middleware-cache.rb +1 -1
  33. data/test/test-middleware-instance-name.rb +32 -10
  34. data/test/test-middleware-jsonp.rb +14 -2
  35. data/test/test-middleware-nginx-raw-uri.rb +1 -1
  36. data/test/test-middleware-range.rb +1 -1
  37. metadata +156 -156
  38. data/lib/racknga/will_paginate.rb +0 -48
@@ -14,10 +14,11 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  require 'digest'
20
20
  require 'yaml'
21
+ require 'zlib'
21
22
  require 'racknga/cache_database'
22
23
 
23
24
  module Racknga
@@ -168,13 +169,15 @@ module Racknga
168
169
  now = Time.now
169
170
  headers = Rack::Utils::HeaderHash.new(headers)
170
171
  headers["Last-Modified"] ||= now.httpdate
171
- stringified_body = ''
172
+ encoded_body = ''.force_encoding("ASCII-8BIT")
173
+ deflater = ::Zlib::Deflate.new
172
174
  body.each do |data|
173
- stringified_body << data
175
+ encoded_body << deflater.deflate(data)
174
176
  end
177
+ body.close if body.respond_to?(:close)
178
+ encoded_body << deflater.finish
175
179
  headers = headers.to_hash
176
180
  encoded_headers = headers.to_yaml
177
- encoded_body = stringified_body.force_encoding("ASCII-8BIT")
178
181
  cache[key] = {
179
182
  :status => status,
180
183
  :headers => encoded_headers,
@@ -183,7 +186,7 @@ module Racknga
183
186
  :age => age,
184
187
  :created_at => now,
185
188
  }
186
- body = [stringified_body]
189
+ body = Inflater.new(encoded_body)
187
190
  log("store", request)
188
191
  [status, headers, body]
189
192
  end
@@ -199,7 +202,7 @@ module Racknga
199
202
  end
200
203
 
201
204
  log("hit", request)
202
- [status, YAML.load(headers), [body]]
205
+ [status, YAML.load(headers), Inflater.new(body)]
203
206
  end
204
207
 
205
208
  def compute_checksum(status, encoded_headers, encoded_body)
@@ -227,6 +230,17 @@ module Racknga
227
230
  runtime = Time.now - start_time
228
231
  logger.log("cache-#{tag}", request.fullpath, :runtime => runtime)
229
232
  end
233
+
234
+ # @private
235
+ class Inflater
236
+ def initialize(deflated_string)
237
+ @deflated_string = deflated_string
238
+ end
239
+
240
+ def each
241
+ yield ::Zlib::Inflate.inflate(@deflated_string)
242
+ end
243
+ end
230
244
  end
231
245
  end
232
246
  end
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module Racknga
20
20
  module Middleware
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  require 'racknga/exception_mail_notifier'
20
20
 
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
3
  # Copyright (C) 2011 Ryo Onodera <onodera@clear-code.com>
4
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
4
5
  #
5
6
  # This library is free software; you can redistribute it and/or
6
7
  # modify it under the terms of the GNU Lesser General Public
@@ -14,7 +15,7 @@
14
15
  #
15
16
  # You should have received a copy of the GNU Lesser General Public
16
17
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19
 
19
20
  module Racknga
20
21
  module Middleware
@@ -23,12 +24,18 @@ module Racknga
23
24
  # server when your Rack applications are deployed behind
24
25
  # load balancers.
25
26
  #
26
- # Usage:
27
+ # @example A simple usage
27
28
  # require "racknga"
28
29
  # use Racknga::Middleware::InstanceName
29
30
  # run YourApplication
30
31
  class InstanceName
31
32
  attr_reader :header
33
+ # @param [application] application rack application.
34
+ # @param [Hash] options options to create header.
35
+ # @option options [String] :header_name ("Responsed-By") header name.
36
+ # @option options [String] :application_name (application.class.name)
37
+ # application name.
38
+ # @option options [Integer] :version application version.
32
39
  def initialize(application, options={})
33
40
  @application = application
34
41
  @options = options
@@ -57,7 +64,14 @@ module Racknga
57
64
  end
58
65
 
59
66
  def revision
60
- `git describe --abbrev=7 HEAD`.strip # XXX be SCM-agonostic
67
+ case using_scm_name
68
+ when :git
69
+ `git describe --abbrev=7 HEAD`.strip
70
+ when :subversion
71
+ `LANG=C svn info | grep Revision`.strip
72
+ else
73
+ nil
74
+ end
61
75
  end
62
76
 
63
77
  def server
@@ -68,17 +82,15 @@ module Racknga
68
82
  `id --user --name`.strip
69
83
  end
70
84
 
71
- CURRENT_BRANCH_MARKER = /\A\* /
72
85
  def branch
73
- current_branch = nil
74
- `git branch -a`.each_line do |line|
75
- case line
76
- when CURRENT_BRANCH_MARKER
77
- current_branch = line.sub(CURRENT_BRANCH_MARKER, "").strip
78
- break
79
- end
86
+ case using_scm_name
87
+ when :git
88
+ git_branch_name
89
+ when :subversion
90
+ subversion_branch_name
91
+ else
92
+ nil
80
93
  end
81
- current_branch
82
94
  end
83
95
 
84
96
  def ruby
@@ -159,6 +171,47 @@ module Racknga
159
171
  nil
160
172
  end
161
173
  end
174
+
175
+ SVN_URL_KEY = /\AURL:.*/
176
+ SVN_REPOSITORY_ROOT_KEY = /\ARepository Root:.*/
177
+ SVN_KEY = /\A.*:/
178
+ SVN_BRANCHES_NAME = /\A\/branches\//
179
+ def subversion_branch_name
180
+ url = ""
181
+ repository_root = ""
182
+
183
+ `LANG=C svn info`.each_line do |line|
184
+ case line
185
+ when SVN_URL_KEY
186
+ url = line.sub(SVN_KEY, "").strip
187
+ when SVN_REPOSITORY_ROOT_KEY
188
+ repository_root = line.sub(SVN_KEY, "").strip
189
+ end
190
+ end
191
+ base_path = url.sub(/#{Regexp.escape(repository_root)}/, "")
192
+ base_path.sub(SVN_BRANCHES_NAME, "")
193
+ end
194
+
195
+ GIT_CURRENT_BRANCH_MARKER = /\A\* /
196
+ def git_branch_name
197
+ `git branch -a`.each_line do |line|
198
+ case line
199
+ when GIT_CURRENT_BRANCH_MARKER
200
+ return line.sub(GIT_CURRENT_BRANCH_MARKER, "").strip
201
+ end
202
+ end
203
+ nil
204
+ end
205
+
206
+ def using_scm_name
207
+ if File.exist?(".git")
208
+ :git
209
+ elsif File.exist?(".svn")
210
+ :subversion
211
+ else
212
+ nil
213
+ end
214
+ end
162
215
  end
163
216
  end
164
217
  end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2010-2012 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module Racknga
20
20
  module Middleware
@@ -91,7 +91,7 @@ module Racknga
91
91
  header_hash = Rack::Utils::HeaderHash.new(headers)
92
92
  return [status, headers, body] unless json_response?(header_hash)
93
93
  body = Writer.new(callback, body)
94
- update_content_type(header_hash)
94
+ update_header_hash(header_hash, body)
95
95
  [status, header_hash, body]
96
96
  end
97
97
 
@@ -122,6 +122,11 @@ module Racknga
122
122
  media_type == "text/javascript"
123
123
  end
124
124
 
125
+ def update_header_hash(header_hash, body)
126
+ update_content_type(header_hash)
127
+ update_content_length(header_hash, body)
128
+ end
129
+
125
130
  def update_content_type(header_hash)
126
131
  content_type = header_hash["Content-Type"]
127
132
  media_type, parameters = content_type.split(/\s*;\s*/, 2)
@@ -132,17 +137,31 @@ module Racknga
132
137
  header_hash["Content-Type"] = updated_content_type
133
138
  end
134
139
 
140
+ def update_content_length(header_hash, body)
141
+ return unless header_hash["Content-Length"]
142
+
143
+ content_length = header_hash["Content-Length"].to_i
144
+ updated_content_length = content_length + body.additional_content_length
145
+ header_hash["Content-Length"] = updated_content_length.to_s
146
+ end
147
+
135
148
  # @private
136
149
  class Writer
137
150
  def initialize(callback, body)
138
151
  @callback = callback
139
152
  @body = body
153
+ @header = "#{@callback}("
154
+ @footer = ");"
140
155
  end
141
156
 
142
157
  def each(&block)
143
- block.call("#{@callback}(")
158
+ block.call(@header)
144
159
  @body.each(&block)
145
- block.call(");")
160
+ block.call(@footer)
161
+ end
162
+
163
+ def additional_content_length
164
+ @header.bytesize + @footer.bytesize
146
165
  end
147
166
  end
148
167
  end
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  require 'racknga/log_database'
20
20
 
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module Racknga
20
20
  module Middleware
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  require 'time'
20
20
 
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module Racknga
20
20
  class ReverseLineReader
data/lib/racknga/utils.rb CHANGED
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module Racknga
20
20
  module Utils
@@ -14,8 +14,8 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module Racknga
20
- VERSION = '0.9.3'
20
+ VERSION = '0.9.4'
21
21
  end
data/lib/racknga.rb CHANGED
@@ -14,13 +14,14 @@
14
14
  #
15
15
  # You should have received a copy of the GNU Lesser General Public
16
16
  # License along with this library; if not, write to the Free Software
17
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  require 'rack'
20
20
 
21
21
  require 'racknga/version'
22
22
  require 'racknga/utils'
23
23
  require "racknga/access_log_parser"
24
+ require 'racknga/api-keys'
24
25
  require 'racknga/middleware/deflater'
25
26
  require 'racknga/middleware/exception_notifier'
26
27
  require 'racknga/middleware/jsonp'
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  #
3
- # Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2010-2013 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -23,16 +23,11 @@ require 'rubygems'
23
23
 
24
24
  mode = ARGV[0]
25
25
 
26
- def passenger_status_path(gem_path)
27
- File.join(gem_path, "bin", "passenger-status")
28
- end
29
-
30
26
  @label = ENV["label"]
31
27
  @pid_file = ENV["pid_file"]
32
28
  @ruby = ENV["ruby"] || Gem.ruby
33
- @gem_path = ((ENV["GEM_HOME"] || '').split(/:/) + Gem.path).find do |path|
34
- File.exist?(passenger_status_path(path))
35
- end
29
+ passenger_spec = Gem::Specification.find_by_name("passenger")
30
+ @passenger_status = passenger_spec.bin_file("passenger-status")
36
31
 
37
32
  if @label
38
33
  parameter_prefix = /\Apassenger_(?:#{@label}_)?application_/
@@ -40,7 +35,7 @@ else
40
35
  parameter_prefix = /\Apassenger_application_/
41
36
  end
42
37
  parameter = File.basename($0).gsub(parameter_prefix, '')
43
- if /_(sessions|processed|uptime)\z/ =~ parameter
38
+ if /_(\S+)\z/ =~ parameter
44
39
  @application = $PREMATCH
45
40
  @type = $1
46
41
  @application = nil if @application and @application.empty?
@@ -57,28 +52,25 @@ def passenger_status
57
52
  else
58
53
  pid = nil
59
54
  end
60
- result = `#{@ruby} #{passenger_status_path(@gem_path)} #{pid}`
55
+ result = `#{@ruby} #{@passenger_status} #{pid}`
61
56
  [$?.success?, result]
62
57
  end
63
58
 
64
- def parse_uptime(uptime)
65
- uptime_in_minutes = 0
66
- if /\A(?:(?:(\d+)h\s+)?(\d+)m\s+)?(\d+)s\z/ =~ uptime
59
+ def parse_time(time)
60
+ time_in_minutes = 0
61
+ if /\A(?:(?:(\d+)h\s+)?(\d+)m\s+)?(\d+)s\z/ =~ time
67
62
  hours = $1.to_i
68
63
  minutes = $2.to_i
69
64
  seconds = $3.to_i
70
- uptime_in_minutes = minutes + hours * 60
65
+ time_in_minutes = minutes + hours * 60
71
66
  end
72
- uptime_in_minutes
67
+ time_in_minutes
73
68
  end
74
69
 
75
70
  def extract_application_name(path)
76
71
  components = path.split(/\//)
77
- ignore_components = ["current"]
78
- while ignore_components.include?(components.last)
79
- components.pop
80
- end
81
- components.pop
72
+ application_name, tag = components.last.split(/#/)
73
+ application_name
82
74
  end
83
75
 
84
76
  def parse_result(result)
@@ -86,34 +78,47 @@ def parse_result(result)
86
78
  section = nil
87
79
  application_name = nil
88
80
  result.each_line do |line|
89
- case section
90
- when "Application groups"
91
- case line.chomp
92
- when /\A(.+):\s*\z/
93
- path = $1
94
- application_name = extract_application_name(path)
95
- sections[section] << [application_name, []]
96
- when /\A\s+\*\s+
97
- PID:\s+(\d+)\s+
98
- Sessions:\s+(\d+)\s+
99
- Processed:\s+(\d+)\s+
100
- Uptime:\s+(.+)\z/x
101
- pid = $1.to_i
102
- sessions = $2.to_i
103
- processed = $3.to_i
104
- uptime = parse_uptime($4)
105
- _application_name, processes = sections[section].last
106
- processes << {
107
- :pid => pid,
108
- :sessions => sessions,
109
- :processed => processed,
110
- :uptime => uptime
111
- }
112
- end
81
+ case line
82
+ when /-+\s+(.+)\s+-+/
83
+ section = $1
84
+ sections[section] = []
113
85
  else
114
- if /-+\s+(.+)\s+-+/ =~ line
115
- section = $1
116
- sections[section] = []
86
+ case section
87
+ when "Application groups"
88
+ case line.chomp
89
+ when /\A(\/.+):\s*\z/
90
+ path = $1
91
+ application_name = extract_application_name(path)
92
+ sections[section] << [application_name, []]
93
+ when /\A\s+\*\s+
94
+ PID:\s+(\d+)\s+
95
+ Sessions:\s+(\d+)\s+
96
+ Processed:\s+(\d+)\s+
97
+ Uptime:\s+(.+)\z/x
98
+ pid = $1.to_i
99
+ sessions = $2.to_i
100
+ processed = $3.to_i
101
+ uptime = parse_time($4)
102
+ _application_name, processes = sections[section].last
103
+ processes << {
104
+ :pid => pid,
105
+ :sessions => sessions,
106
+ :processed => processed,
107
+ :uptime => uptime
108
+ }
109
+ when /\A\s+
110
+ CPU:\s+(\d+)%\s+
111
+ Memory\s*:\s+(\d+)M\s+
112
+ Last\sused:\s+(.+)(?:\s+ago)\z/x
113
+ cpu = $1.to_i
114
+ memory = $2.to_i * 1024 * 1024
115
+ last_used = parse_time($3)
116
+ _application_name, processes = sections[section].last
117
+ process = processes.last
118
+ process[:cpu] = cpu
119
+ process[:memory] = memory
120
+ process[:last_used] = last_used
121
+ end
117
122
  end
118
123
  end
119
124
  end
@@ -138,6 +143,12 @@ def vlabel
138
143
  "number of processed sessions"
139
144
  when "uptime"
140
145
  "uptime by minutes"
146
+ when "cpu"
147
+ "CPU usage in percent"
148
+ when "memory"
149
+ "memory usage"
150
+ when "last_used"
151
+ "last used by minutes"
141
152
  else
142
153
  "unknown"
143
154
  end
@@ -219,6 +230,9 @@ when "suggest"
219
230
  puts "#{application}_sessions"
220
231
  puts "#{application}_processed"
221
232
  puts "#{application}_uptime"
233
+ puts "#{application}_cpu"
234
+ puts "#{application}_memory"
235
+ puts "#{application}_last_used"
222
236
  end
223
237
  exit(true)
224
238
  end
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  #
3
- # Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2010-2013 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -22,16 +22,11 @@ require 'rubygems'
22
22
 
23
23
  mode = ARGV[0]
24
24
 
25
- def passenger_status_path(gem_path)
26
- File.join(gem_path, "bin", "passenger-status")
27
- end
28
-
29
25
  @label = ENV["label"]
30
26
  @pid_file = ENV["pid_file"]
31
27
  @ruby = ENV["ruby"] || Gem.ruby
32
- @gem_path = ((ENV["GEM_HOME"] || '').split(/:/) + Gem.path).find do |path|
33
- File.exist?(passenger_status_path(path))
34
- end
28
+ passenger_spec = Gem::Specification.find_by_name("passenger")
29
+ @passenger_status = passenger_spec.bin_file("passenger-status")
35
30
 
36
31
  def passenger_status
37
32
  if @pid_file
@@ -42,32 +37,60 @@ def passenger_status
42
37
  else
43
38
  pid = nil
44
39
  end
45
- result = `#{@ruby} #{passenger_status_path(@gem_path)} #{pid}`
40
+ result = `#{@ruby} #{@passenger_status} #{pid}`
46
41
  [$?.success?, result]
47
42
  end
48
43
 
44
+ def label_to_key(label)
45
+ label.downcase.gsub(/[ -]+/, "_")
46
+ end
47
+
48
+ def extract_application_name(path)
49
+ components = path.split(/\//)
50
+ application_name, tag = components.last.split(/#/)
51
+ application_name
52
+ end
53
+
49
54
  def parse_result(result)
50
55
  sections = {}
51
56
  section = nil
52
57
  result.each_line do |line|
53
- case section
54
- when "General information"
55
- case line.chomp
56
- when /\A(\S+)\s*=\s*(\d+)\z/
57
- key = $1
58
- value = $2.to_i
59
- sections[section] << {:key => key, :label => key, :value => value}
60
- when /\A(Waiting on global queue):\s*(\d+)\z/
61
- label = $1
62
- value = $2.to_i
63
- sections[section] << {:key => "global_queue",
64
- :label => label,
65
- :value => value}
66
- end
58
+ case line
59
+ when /-+\s+(.+)\s+-+/
60
+ section = $1
61
+ sections[section] = []
67
62
  else
68
- if /-+\s+(.+)\s+-+/ =~ line
69
- section = $1
70
- sections[section] = []
63
+ case section
64
+ when "General information"
65
+ case line.chomp
66
+ when /\A(.+):\s*(\d+)\z/
67
+ label = $1.strip
68
+ value = $2.to_i
69
+ key = label_to_key(label)
70
+ sections[section] << {
71
+ :key => key,
72
+ :label => label,
73
+ :value => value,
74
+ }
75
+ end
76
+ when "Application groups"
77
+ case line.chomp
78
+ when /\A(\/.+):\s*\z/
79
+ path = $1
80
+ application_name = extract_application_name(path)
81
+ sections[section] << [application_name, []]
82
+ when /\A\s+(.+):\s*(\d+)\z/
83
+ label = $1.strip
84
+ value = $2.to_i
85
+ _application_name, attributes = sections[section].last
86
+ key = "#{_application_name}_#{label_to_key(label)}"
87
+ label = "#{label}: #{_application_name}"
88
+ attributes << {
89
+ :key => key,
90
+ :label => label,
91
+ :value => value,
92
+ }
93
+ end
71
94
  end
72
95
  end
73
96
  end
@@ -95,12 +118,16 @@ graph_vlabel number of processes
95
118
 
96
119
  EOC
97
120
  have_stack_base = false
98
- sections["General information"].each do |attributes|
99
- key = attributes[:key]
121
+ attributes = sections["General information"]
122
+ sections["Application groups"].each do |_, application_attributes|
123
+ attributes += application_attributes
124
+ end
125
+ attributes.each do |attribute|
126
+ key = attribute[:key]
100
127
  next if key == "count"
101
- puts("#{key}.label #{attributes[:label]}")
128
+ puts("#{key}.label #{attribute[:label]}")
102
129
  case key
103
- when "max", "global_queue"
130
+ when /max/, /queue/
104
131
  draw = "LINE2"
105
132
  else
106
133
  if have_stack_base
@@ -110,7 +137,7 @@ EOC
110
137
  have_stack_base = true
111
138
  end
112
139
  end
113
- puts("#{attributes[:key]}.draw #{draw}")
140
+ puts("#{attribute[:key]}.draw #{draw}")
114
141
  end
115
142
  end
116
143
 
@@ -119,8 +146,12 @@ def report
119
146
  exit(false) unless success
120
147
 
121
148
  sections = parse_result(result)
122
- sections["General information"].each do |attributes|
123
- puts("#{attributes[:key]}.value #{attributes[:value]}")
149
+ attributes = sections["General information"]
150
+ sections["Application groups"].each do |_, application_attributes|
151
+ attributes += application_attributes
152
+ end
153
+ attributes.each do |attribute|
154
+ puts("#{attribute[:key]}.value #{attribute[:value]}")
124
155
  end
125
156
  end
126
157