racknga 0.9.2 → 0.9.4

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