racknga 0.9.1 → 0.9.2
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/Gemfile +30 -0
- data/README.textile +52 -0
- data/Rakefile +237 -117
- data/doc/text/news.textile +32 -0
- data/lib/racknga/cache_database.rb +18 -3
- data/lib/racknga/exception_mail_notifier.rb +76 -15
- data/lib/racknga/log_database.rb +21 -4
- data/lib/racknga/middleware/cache.rb +75 -14
- data/lib/racknga/middleware/deflater.rb +37 -0
- data/lib/racknga/middleware/exception_notifier.rb +17 -0
- data/lib/racknga/middleware/instance_name.rb +134 -0
- data/lib/racknga/middleware/jsonp.rb +82 -10
- data/lib/racknga/middleware/log.rb +18 -3
- data/lib/racknga/middleware/range.rb +10 -0
- data/lib/racknga/nginx_access_log_parser.rb +139 -0
- data/lib/racknga/reverse_line_reader.rb +73 -0
- data/lib/racknga/version.rb +2 -2
- data/lib/racknga/will_paginate.rb +1 -0
- data/lib/racknga.rb +3 -1
- data/license/lgpl-2.1.txt +502 -0
- data/munin/plugins/{passenger_domain_ → passenger_application_} +63 -47
- data/test/racknga-test-utils.rb +9 -12
- data/test/run-test.rb +5 -10
- data/test/test-middleware-cache.rb +77 -0
- data/test/test-middleware-instance-name.rb +98 -0
- data/test/test-middleware-jsonp.rb +32 -9
- data/test/test-middleware-range.rb +5 -4
- data/test/test-nginx-log-parser.rb +214 -0
- metadata +106 -56
- data/NEWS.ja.rdoc +0 -16
- data/NEWS.rdoc +0 -9
- data/README.ja.rdoc +0 -80
- data/README.rdoc +0 -51
- data/html/footer.html.erb +0 -33
- data/html/head.html.erb +0 -4
- data/html/header.html.erb +0 -17
- data/test/fixtures/rabbit-theme-change.ogv +0 -0
@@ -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-2011 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
|
@@ -20,9 +20,20 @@ require 'racknga/log_database'
|
|
20
20
|
|
21
21
|
module Racknga
|
22
22
|
module Middleware
|
23
|
+
# This is a middleware that puts access logs to groonga
|
24
|
+
# database. It may useful for OLAP (OnLine Analytical
|
25
|
+
# Processing).
|
26
|
+
#
|
27
|
+
# Usage:
|
28
|
+
# use Racnkga::Middleware::Log, :database_path => "var/log/db"
|
29
|
+
# run YourApplication
|
30
|
+
#
|
31
|
+
# @see Racknga::LogDatabase
|
23
32
|
class Log
|
24
|
-
|
33
|
+
LOGGER = "racknga.logger"
|
25
34
|
|
35
|
+
# @option options [String] :database_path the
|
36
|
+
# database path to be stored caches.
|
26
37
|
def initialize(application, options={})
|
27
38
|
@application = application
|
28
39
|
@options = Utils.normalize_options(options || {})
|
@@ -32,8 +43,9 @@ module Racknga
|
|
32
43
|
@logger = Logger.new(@database)
|
33
44
|
end
|
34
45
|
|
46
|
+
# For Rack.
|
35
47
|
def call(environment)
|
36
|
-
environment[
|
48
|
+
environment[LOGGER] = @logger
|
37
49
|
|
38
50
|
start_time = Time.now
|
39
51
|
status, headers, body = @application.call(environment)
|
@@ -45,10 +57,12 @@ module Racknga
|
|
45
57
|
[status, headers, body]
|
46
58
|
end
|
47
59
|
|
60
|
+
# ensures creating cache database.
|
48
61
|
def ensure_database
|
49
62
|
@database.ensure_database
|
50
63
|
end
|
51
64
|
|
65
|
+
# close the cache database.
|
52
66
|
def close_database
|
53
67
|
@database.close_database
|
54
68
|
end
|
@@ -77,6 +91,7 @@ module Racknga
|
|
77
91
|
:runtime => request_time)
|
78
92
|
end
|
79
93
|
|
94
|
+
# @private
|
80
95
|
class Logger
|
81
96
|
def initialize(database)
|
82
97
|
@database = database
|
@@ -20,11 +20,20 @@ require 'time'
|
|
20
20
|
|
21
21
|
module Racknga
|
22
22
|
module Middleware
|
23
|
+
# This is a middleware that provides HTTP range request
|
24
|
+
# (partial request) support. For example, HTTP range
|
25
|
+
# request is used for playing a video on the way.
|
26
|
+
#
|
27
|
+
# Usage:
|
28
|
+
# require "racknga"
|
29
|
+
# use Racknga::Middleware::Range
|
30
|
+
# run YourApplication
|
23
31
|
class Range
|
24
32
|
def initialize(application)
|
25
33
|
@application = application
|
26
34
|
end
|
27
35
|
|
36
|
+
# For Rack.
|
28
37
|
def call(environment)
|
29
38
|
status, headers, body = @application.call(environment)
|
30
39
|
return [status, headers, body] if status != 200
|
@@ -109,6 +118,7 @@ module Racknga
|
|
109
118
|
nil
|
110
119
|
end
|
111
120
|
|
121
|
+
# @private
|
112
122
|
class RangeStream
|
113
123
|
def initialize(body, first_byte, length)
|
114
124
|
@body = body
|
@@ -0,0 +1,139 @@
|
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
|
+
|
19
|
+
require "racknga/reverse_line_reader"
|
20
|
+
|
21
|
+
module Racknga
|
22
|
+
# Supported formats:
|
23
|
+
# * combined (default format)
|
24
|
+
# * combined_with_time (custom format for Passenger)
|
25
|
+
#
|
26
|
+
# Configurations in nginx:
|
27
|
+
# * combined
|
28
|
+
# log_format combined '$remote_addr - $remote_user [$time_local] '
|
29
|
+
# '"$request" $status $body_bytes_sent '
|
30
|
+
# '"$http_referer" "$http_user_agent"';
|
31
|
+
# access_log log/access.log combined
|
32
|
+
#
|
33
|
+
# * combined_with_time
|
34
|
+
# log_format combined_with_time '$remote_addr - $remote_user '
|
35
|
+
# '[$time_local, $upstream_http_x_runtime, $request_time] '
|
36
|
+
# '"$request" $status $body_bytes_sent '
|
37
|
+
# '"$http_referer" "$http_user_agent"';
|
38
|
+
# access_log log/access.log combined_with_time
|
39
|
+
class NginxAccessLogParser
|
40
|
+
include Enumerable
|
41
|
+
|
42
|
+
class FormatError < StandardError
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(line_reader)
|
46
|
+
@line_reader = line_reader
|
47
|
+
end
|
48
|
+
|
49
|
+
def each
|
50
|
+
@line_reader.each do |line|
|
51
|
+
line.force_encoding("UTF-8")
|
52
|
+
yield(parse_line(line)) if line.valid_encoding?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
REMOTE_ADDRESS = '(?:\d{1,3}\.){3}\d{1,3}'
|
57
|
+
REMOTE_USER = '[^ ]+'
|
58
|
+
TIME_LOCAL = '[^ ]+ \+\d{4}'
|
59
|
+
RUNTIME = '(?:[\d.]+|-)'
|
60
|
+
REQUEST_TIME = '[\d.]+'
|
61
|
+
REQUEST = '.*?'
|
62
|
+
STATUS = '\d{3}'
|
63
|
+
BODY_BYTES_SENT = '\d+'
|
64
|
+
HTTP_REFERER = '.*?'
|
65
|
+
HTTP_USER_AGENT = '(?:\\"|[^\"])*?' # '
|
66
|
+
LOG_FORMAT =
|
67
|
+
/\A(#{REMOTE_ADDRESS}) - (#{REMOTE_USER}) \[(#{TIME_LOCAL})(?:, (#{RUNTIME}), (#{REQUEST_TIME}))?\] "(#{REQUEST})" (#{STATUS}) (#{BODY_BYTES_SENT}) "(#{HTTP_REFERER})" "(#{HTTP_USER_AGENT})"\n\z/
|
68
|
+
def parse_line(line)
|
69
|
+
if line =~ LOG_FORMAT
|
70
|
+
last_match = Regexp.last_match
|
71
|
+
options = {}
|
72
|
+
options[:remote_address] = last_match[1]
|
73
|
+
options[:remote_user] = last_match[2]
|
74
|
+
parse_time_local(last_match[3], options)
|
75
|
+
options[:runtime] = last_match[4].to_f
|
76
|
+
options[:request_time] = last_match[5].to_f
|
77
|
+
options[:request] = last_match[6]
|
78
|
+
options[:status] = last_match[7].to_i
|
79
|
+
options[:body_bytes_sent] = last_match[8].to_i
|
80
|
+
options[:http_referer] = last_match[9]
|
81
|
+
options[:http_user_agent] = last_match[10]
|
82
|
+
LogEntry.new(options)
|
83
|
+
else
|
84
|
+
raise FormatError.new("ill-formatted log entry: #{line.inspect} !~ #{LOG_FORMAT}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_time_local(token, options)
|
89
|
+
day, month, year, hour, minute, second, _time_zone = token.split(/[\/: ]/)
|
90
|
+
options[:time_local] = Time.local(year, month, day, hour, minute, second)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class ReversedNginxAccessLogParser < NginxAccessLogParser
|
95
|
+
def initialize(line_reader)
|
96
|
+
@line_reader = ReverseLineReader.new(line_reader)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class LogEntry
|
101
|
+
ATTRIBUTES = [
|
102
|
+
:remote_address,
|
103
|
+
:remote_user,
|
104
|
+
:time_local,
|
105
|
+
:runtime,
|
106
|
+
:request_time,
|
107
|
+
:request,
|
108
|
+
:status,
|
109
|
+
:body_bytes_sent,
|
110
|
+
:http_referer,
|
111
|
+
:http_user_agent,
|
112
|
+
]
|
113
|
+
|
114
|
+
attr_reader(*ATTRIBUTES)
|
115
|
+
def initialize(options=nil)
|
116
|
+
options ||= {}
|
117
|
+
@remote_address = options[:remote_address]
|
118
|
+
@remote_user = options[:remote_user]
|
119
|
+
@time_local = options[:time_local] || Time.at(0)
|
120
|
+
@runtime = options[:runtime] || 0.0
|
121
|
+
@request_time = options[:request_time] || 0.0
|
122
|
+
@request = options[:request]
|
123
|
+
@status = options[:status]
|
124
|
+
@body_bytes_sent = options[:body_bytes_sent]
|
125
|
+
@http_referer = options[:http_referer]
|
126
|
+
@http_user_agent = options[:http_user_agent]
|
127
|
+
end
|
128
|
+
|
129
|
+
def attributes
|
130
|
+
ATTRIBUTES.collect do |attribute|
|
131
|
+
__send__(attribute)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def ==(other)
|
136
|
+
attributes == other.attributes
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,73 @@
|
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
|
+
|
19
|
+
module Racknga
|
20
|
+
class ReverseLineReader
|
21
|
+
def initialize(io)
|
22
|
+
@io = io
|
23
|
+
@io.seek(0, IO::SEEK_END)
|
24
|
+
@buffer = ""
|
25
|
+
@data = ""
|
26
|
+
end
|
27
|
+
|
28
|
+
def each
|
29
|
+
separator = $/
|
30
|
+
separator_length = separator.length
|
31
|
+
while read_to_buffer
|
32
|
+
loop do
|
33
|
+
index = @buffer.rindex(separator, @buffer.length - 1 - separator_length)
|
34
|
+
break if index.nil? or index.zero?
|
35
|
+
last_line = @buffer.slice!((index + separator_length)..-1)
|
36
|
+
yield(last_line)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
yield(@buffer) unless @buffer.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
BYTES_PER_READ = 4096
|
44
|
+
def read
|
45
|
+
position = @io.pos
|
46
|
+
if position < BYTES_PER_READ
|
47
|
+
bytes_per_read = position
|
48
|
+
else
|
49
|
+
bytes_per_read = BYTES_PER_READ
|
50
|
+
end
|
51
|
+
|
52
|
+
if bytes_per_read.zero?
|
53
|
+
@data.replace("")
|
54
|
+
else
|
55
|
+
@io.seek(-bytes_per_read, IO::SEEK_CUR)
|
56
|
+
@io.read(bytes_per_read, @data)
|
57
|
+
@io.seek(-bytes_per_read, IO::SEEK_CUR)
|
58
|
+
end
|
59
|
+
|
60
|
+
@data
|
61
|
+
end
|
62
|
+
|
63
|
+
def read_to_buffer
|
64
|
+
data = read.force_encoding("BINARY")
|
65
|
+
if data.empty?
|
66
|
+
false
|
67
|
+
else
|
68
|
+
@buffer.insert(0, data)
|
69
|
+
true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/racknga/version.rb
CHANGED
@@ -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-2011 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
|
@@ -17,5 +17,5 @@
|
|
17
17
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
18
|
|
19
19
|
module Racknga
|
20
|
-
VERSION = '0.9.
|
20
|
+
VERSION = '0.9.2'
|
21
21
|
end
|
data/lib/racknga.rb
CHANGED
@@ -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-2011 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
|
@@ -20,7 +20,9 @@ require 'rack'
|
|
20
20
|
|
21
21
|
require 'racknga/version'
|
22
22
|
require 'racknga/utils'
|
23
|
+
require "racknga/nginx_access_log_parser"
|
23
24
|
require 'racknga/middleware/deflater'
|
24
25
|
require 'racknga/middleware/exception_notifier'
|
25
26
|
require 'racknga/middleware/jsonp'
|
26
27
|
require 'racknga/middleware/range'
|
28
|
+
require "racknga/middleware/instance_name"
|