racknga 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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