racknga 0.9.2 → 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 (39) 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 +20 -0
  6. data/lib/racknga/access_log_parser.rb +147 -0
  7. data/lib/racknga/api-keys.rb +40 -0
  8. data/lib/racknga/cache_database.rb +15 -5
  9. data/lib/racknga/exception_mail_notifier.rb +6 -6
  10. data/lib/racknga/log_database.rb +2 -1
  11. data/lib/racknga/log_entry.rb +85 -0
  12. data/lib/racknga/middleware/auth/api-key.rb +95 -0
  13. data/lib/racknga/middleware/cache.rb +22 -8
  14. data/lib/racknga/middleware/deflater.rb +13 -3
  15. data/lib/racknga/middleware/exception_notifier.rb +1 -2
  16. data/lib/racknga/middleware/instance_name.rb +92 -9
  17. data/lib/racknga/middleware/jsonp.rb +25 -5
  18. data/lib/racknga/middleware/log.rb +8 -3
  19. data/lib/racknga/middleware/nginx_raw_uri.rb +65 -0
  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 +4 -2
  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-nginx-log-parser.rb → test-access-log-parser.rb} +115 -26
  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 +50 -16
  34. data/test/test-middleware-jsonp.rb +14 -2
  35. data/test/test-middleware-nginx-raw-uri.rb +70 -0
  36. data/test/test-middleware-range.rb +1 -1
  37. metadata +159 -155
  38. data/lib/racknga/nginx_access_log_parser.rb +0 -139
  39. data/lib/racknga/will_paginate.rb +0 -48
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Ryo Onodera <onodera@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ module Racknga
20
+ module Middleware
21
+ # NOTE:
22
+ # This is a middleware that restores the unprocessed URI client requests
23
+ # as is. Usually, nginx-passenger stack unescapes percent encoding in URI
24
+ # and resolve relative paths (ie "." and "..").
25
+ # Most of time, processed URI isn't program. However, if you want to
26
+ # distinguish %2F (ie "/") from "/", it is.
27
+ #
28
+ # Passenger 3.x or later is required.
29
+ #
30
+ # Use this with following nginx configuration:
31
+ #
32
+ # ... {
33
+ # ...
34
+ # passenger_set_cgi_param HTTP_X_RAW_REQUEST_URI $request_uri;
35
+ # }
36
+ #
37
+ # Usage:
38
+ # require "racknga"
39
+ # use Racknga::Middleware::NginxRawURI
40
+ # run YourApplication
41
+ class NginxRawURI
42
+ RAW_REQUEST_URI_HEADER_NAME = "HTTP_X_RAW_REQUEST_URI"
43
+ def initialize(application)
44
+ @application = application
45
+ end
46
+
47
+ # For Rack.
48
+ def call(environment)
49
+ raw_uri = environment[RAW_REQUEST_URI_HEADER_NAME]
50
+
51
+ if raw_uri
52
+ restore_raw_uri(environment, raw_uri)
53
+ end
54
+
55
+ @application.call(environment)
56
+ end
57
+
58
+ private
59
+ def restore_raw_uri(environment, raw_uri)
60
+ environment["PATH_INFO"] = raw_uri.split("?").first
61
+ environment["REQUEST_URI"] = raw_uri
62
+ end
63
+ end
64
+ end
65
+ 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 '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.2'
20
+ VERSION = '0.9.4'
21
21
  end
data/lib/racknga.rb CHANGED
@@ -14,15 +14,17 @@
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
- require "racknga/nginx_access_log_parser"
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'
27
28
  require 'racknga/middleware/range'
28
29
  require "racknga/middleware/instance_name"
30
+ require "racknga/middleware/nginx_raw_uri"
@@ -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
 
@@ -12,12 +12,13 @@
12
12
  #
13
13
  # You should have received a copy of the GNU Lesser General Public
14
14
  # License along with this library; if not, write to the Free Software
15
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
  require "test/unit/capybara"
18
18
  require 'json'
19
19
 
20
20
  require 'racknga'
21
+ require 'racknga/middleware/auth/api-key'
21
22
  require 'racknga/middleware/cache'
22
23
  require 'racknga/middleware/instance_name'
23
24
 
data/test/run-test.rb CHANGED
@@ -14,12 +14,10 @@
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
  $VERBOSE = true
20
20
 
21
- $KCODE = "u" if RUBY_VERSION < "1.9"
22
-
23
21
  require 'pathname'
24
22
 
25
23
  base_dir = Pathname(__FILE__).dirname.parent.expand_path