passenger 4.0.45 → 4.0.46
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/.editorconfig +19 -0
- data/CHANGELOG +47 -0
- data/CONTRIBUTING.md +9 -1
- data/CONTRIBUTORS +4 -0
- data/Vagrantfile +7 -3
- data/build/agents.rb +1 -0
- data/build/misc.rb +6 -4
- data/dev/vagrant/bashrc +2 -0
- data/doc/Design and Architecture.txt +9 -7
- data/doc/Users guide Apache.idmap.txt +2 -0
- data/doc/Users guide Apache.txt +24 -4
- data/doc/Users guide Nginx.idmap.txt +4 -0
- data/doc/Users guide Nginx.txt +23 -4
- data/doc/images/code_walkthrough.jpg +0 -0
- data/doc/users_guide_snippets/installation.txt +38 -0
- data/ext/common/AgentsStarter.h +6 -1
- data/ext/common/ApplicationPool2/Common.h +17 -2
- data/ext/common/ApplicationPool2/DirectSpawner.h +5 -11
- data/ext/common/ApplicationPool2/DummySpawner.h +2 -4
- data/ext/common/ApplicationPool2/ErrorRenderer.h +119 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +159 -11
- data/ext/common/ApplicationPool2/Options.h +16 -7
- data/ext/common/ApplicationPool2/Pool.h +28 -24
- data/ext/common/ApplicationPool2/Process.h +1 -9
- data/ext/common/ApplicationPool2/SmartSpawner.h +15 -18
- data/ext/common/ApplicationPool2/Spawner.h +18 -14
- data/ext/common/ApplicationPool2/SpawnerFactory.h +12 -30
- data/ext/common/Constants.h +1 -1
- data/ext/common/Exceptions.h +15 -2
- data/ext/common/UnionStation/Core.h +9 -0
- data/ext/common/Utils/JsonUtils.h +53 -0
- data/ext/common/Utils/ProcessMetricsCollector.h +1 -1
- data/ext/common/Utils/SpeedMeter.h +7 -3
- data/ext/common/Utils/SystemMetricsCollector.h +8 -6
- data/ext/common/agents/HelperAgent/Main.cpp +4 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +115 -56
- data/ext/nginx/ConfigurationCommands.c +1 -1
- data/ext/nginx/ConfigurationCommands.c.erb +6 -1
- data/ext/nginx/ContentHandler.c +2 -1
- data/ext/nginx/config +1 -1
- data/helper-scripts/node-loader.js +23 -0
- data/helper-scripts/wsgi-loader.py +12 -4
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/active_support3_extensions/init.rb +39 -78
- data/lib/phusion_passenger/constants.rb +3 -1
- data/lib/phusion_passenger/loader_shared_helpers.rb +10 -5
- data/lib/phusion_passenger/nginx/config_options.rb +3 -1
- data/lib/phusion_passenger/packaging.rb +1 -0
- data/lib/phusion_passenger/public_api.rb +108 -16
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +1 -0
- data/lib/phusion_passenger/request_handler.rb +2 -2
- data/lib/phusion_passenger/request_handler/thread_handler.rb +28 -46
- data/lib/phusion_passenger/standalone/command.rb +8 -1
- data/lib/phusion_passenger/standalone/main.rb +0 -1
- data/lib/phusion_passenger/standalone/start_command.rb +4 -0
- data/lib/phusion_passenger/union_station/connection.rb +67 -0
- data/lib/phusion_passenger/{analytics_logger.rb → union_station/core.rb} +55 -256
- data/lib/phusion_passenger/union_station/transaction.rb +168 -0
- data/lib/phusion_passenger/utils.rb +4 -0
- data/lib/phusion_passenger/utils/lock.rb +62 -0
- data/resources/mime.types +1 -0
- data/resources/templates/error_layout.html.template +2 -0
- data/resources/templates/standalone/config.erb +1 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +5 -3
- data/test/cxx/ApplicationPool2/PoolTest.cpp +13 -3
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +16 -13
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +6 -0
- data/test/cxx/FileBackedPipeTest.cpp +1 -1
- data/test/cxx/RequestHandlerTest.cpp +158 -2
- data/test/cxx/ServerInstanceDirTest.cpp +2 -0
- data/test/cxx/TestSupport.h +21 -2
- data/test/cxx/UtilsTest.cpp +1 -0
- data/test/ruby/classic_rails/loader_spec.rb +0 -1
- data/test/ruby/classic_rails/preloader_spec.rb +0 -1
- data/test/ruby/rails3.0/loader_spec.rb +2 -2
- data/test/ruby/rails3.0/preloader_spec.rb +2 -2
- data/test/ruby/rails3.1/loader_spec.rb +2 -2
- data/test/ruby/rails3.1/preloader_spec.rb +2 -2
- data/test/ruby/rails3.2/loader_spec.rb +2 -2
- data/test/ruby/rails3.2/preloader_spec.rb +2 -2
- data/test/ruby/rails4.0/loader_spec.rb +2 -2
- data/test/ruby/rails4.0/preloader_spec.rb +2 -2
- data/test/ruby/request_handler_spec.rb +8 -8
- data/test/ruby/shared/rails/{analytics_logging_extensions_sharedspec.rb → union_station_extensions_sharedspec.rb} +5 -4
- data/test/ruby/union_station_spec.rb +283 -0
- data/test/stub/wsgi/passenger_wsgi.py +41 -5
- metadata +12 -7
- metadata.gz.asc +7 -7
- data/helper-scripts/wsgi-preloader.py +0 -1
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +0 -105
- data/test/ruby/analytics_logger_spec.rb +0 -283
@@ -123,6 +123,11 @@ def struct_field_for(option)
|
|
123
123
|
return "offsetof(#{struct_type_for(option)}, #{field})"
|
124
124
|
end
|
125
125
|
end
|
126
|
+
|
127
|
+
def post_for(option)
|
128
|
+
return option[:post] if option[:post]
|
129
|
+
return "NULL"
|
130
|
+
end
|
126
131
|
%>
|
127
132
|
|
128
133
|
<% for option in LOCATION_CONFIGURATION_OPTIONS %>
|
@@ -133,6 +138,6 @@ end
|
|
133
138
|
<%= setter_function_for(option) %>,
|
134
139
|
<%= struct_for(option) %>,
|
135
140
|
<%= struct_field_for(option) %>,
|
136
|
-
|
141
|
+
<%= post_for(option) %>
|
137
142
|
},
|
138
143
|
<% end %>
|
data/ext/nginx/ContentHandler.c
CHANGED
@@ -533,7 +533,8 @@ create_request(ngx_http_request_t *r)
|
|
533
533
|
b->last = ngx_copy(b->last, "CONTENT_LENGTH",
|
534
534
|
sizeof("CONTENT_LENGTH"));
|
535
535
|
|
536
|
-
b->last = ngx_snprintf(b->last, 10, "%
|
536
|
+
b->last = ngx_snprintf(b->last, 10, "%O",
|
537
|
+
r->headers_in.content_length_n);
|
537
538
|
*b->last++ = (u_char) 0;
|
538
539
|
}
|
539
540
|
|
data/ext/nginx/config
CHANGED
@@ -87,7 +87,7 @@ if [ $ngx_found = yes ]; then
|
|
87
87
|
CORE_LIBS="$CORE_LIBS -lrt"
|
88
88
|
fi
|
89
89
|
|
90
|
-
nginx_version=`grep 'NGINX_VERSION ' src/core/nginx.h | awk '{ print $3 }' | sed 's/"//g'`
|
90
|
+
nginx_version=`grep 'NGINX_VERSION ' src/core/nginx.h | awk '{ print $3 }' | sed 's/"//g' | head -n1`
|
91
91
|
|
92
92
|
nginx_major_version=`echo "$nginx_version" | cut -d . -f 1`
|
93
93
|
have=PASSENGER_NGINX_MAJOR_VERSION value="$nginx_major_version"
|
@@ -128,12 +128,35 @@ function generateServerSocketPath() {
|
|
128
128
|
+ process.pid + "." + ((Math.random() * 0xFFFFFFFF) & 0xFFFFFFF);
|
129
129
|
}
|
130
130
|
|
131
|
+
function addListenerAtBeginning(emitter, event, callback) {
|
132
|
+
var listeners = emitter.listeners(event);
|
133
|
+
var i;
|
134
|
+
|
135
|
+
emitter.removeAllListeners(event);
|
136
|
+
emitter.on(event, callback);
|
137
|
+
for (i = 0; i < listeners.length; i++) {
|
138
|
+
emitter.on(event, listeners[i]);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
131
142
|
function installServer() {
|
132
143
|
var server = this;
|
133
144
|
if (!PhusionPassenger._appInstalled) {
|
134
145
|
PhusionPassenger._appInstalled = true;
|
135
146
|
PhusionPassenger._server = server;
|
136
147
|
|
148
|
+
// Ensure that req.connection.remoteAddress and remotePort return something
|
149
|
+
// instead of undefined. Apps like Etherpad expect it.
|
150
|
+
// See https://github.com/phusion/passenger/issues/1224
|
151
|
+
addListenerAtBeginning(server, 'request', function(req) {
|
152
|
+
req.connection.__defineGetter__('remoteAddress', function() {
|
153
|
+
return '127.0.0.1';
|
154
|
+
});
|
155
|
+
req.connection.__defineGetter__('remotePort', function() {
|
156
|
+
return 0;
|
157
|
+
});
|
158
|
+
});
|
159
|
+
|
137
160
|
var listenTries = 0;
|
138
161
|
doListen(extractCallback(arguments));
|
139
162
|
|
@@ -53,7 +53,11 @@ def handshake_and_read_startup_request():
|
|
53
53
|
line = readline()
|
54
54
|
|
55
55
|
def load_app():
|
56
|
-
|
56
|
+
global options
|
57
|
+
|
58
|
+
sys.path.insert(0, os.getcwd())
|
59
|
+
startup_file = options.get('startup_file', 'passenger_wsgi.py')
|
60
|
+
return imp.load_source('passenger_wsgi', startup_file)
|
57
61
|
|
58
62
|
def create_server_socket():
|
59
63
|
global options
|
@@ -256,9 +260,13 @@ class RequestHandler:
|
|
256
260
|
headers_set[:] = [status, response_headers]
|
257
261
|
return write
|
258
262
|
|
259
|
-
|
260
|
-
|
261
|
-
|
263
|
+
# Django's django.template.base module goes through all WSGI
|
264
|
+
# environment values, and calls each value that is a callable.
|
265
|
+
# No idea why, but we work around that with the `do_it` parameter.
|
266
|
+
def hijack(do_it = False):
|
267
|
+
if do_it:
|
268
|
+
env['passenger.hijacked_socket'] = output_stream
|
269
|
+
return output_stream
|
262
270
|
|
263
271
|
env['passenger.hijack'] = hijack
|
264
272
|
|
data/lib/phusion_passenger.rb
CHANGED
@@ -30,7 +30,7 @@ module PhusionPassenger
|
|
30
30
|
|
31
31
|
PACKAGE_NAME = 'passenger'
|
32
32
|
# Run 'rake ext/common/Constants.h' after changing this number.
|
33
|
-
VERSION_STRING = '4.0.
|
33
|
+
VERSION_STRING = '4.0.46'
|
34
34
|
|
35
35
|
PREFERRED_NGINX_VERSION = '1.6.0'
|
36
36
|
NGINX_SHA256_CHECKSUM = '943ad757a1c3e8b3df2d5c4ddacc508861922e36fa10ea6f8e3a348fc9abfc1a'
|
@@ -28,31 +28,31 @@ module PhusionPassenger
|
|
28
28
|
|
29
29
|
module ActiveSupport3Extensions
|
30
30
|
def self.init!(options, user_options = {})
|
31
|
-
if !
|
31
|
+
if !UnionStationExtension.install!(options, user_options)
|
32
32
|
# Remove code to save memory.
|
33
|
-
PhusionPassenger::ActiveSupport3Extensions.send(:remove_const, :
|
33
|
+
PhusionPassenger::ActiveSupport3Extensions.send(:remove_const, :UnionStationExtension)
|
34
34
|
PhusionPassenger.send(:remove_const, :ActiveSupport3Extensions)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
module ActiveSupport3Extensions
|
40
|
-
class
|
40
|
+
class UnionStationExtension < ActiveSupport::LogSubscriber
|
41
41
|
def self.install!(options, user_options)
|
42
|
-
|
42
|
+
union_station_core = options["union_station_core"]
|
43
43
|
app_group_name = options["app_group_name"]
|
44
|
-
return false if !
|
44
|
+
return false if !union_station_core || !options["analytics"]
|
45
45
|
|
46
46
|
# If the Ruby interpreter supports GC statistics then turn it on
|
47
47
|
# so that the info can be logged.
|
48
48
|
GC.enable_stats if GC.respond_to?(:enable_stats)
|
49
49
|
|
50
50
|
subscriber = self.new(user_options)
|
51
|
-
|
52
|
-
|
51
|
+
UnionStationExtension.attach_to(:action_controller, subscriber)
|
52
|
+
UnionStationExtension.attach_to(:active_record, subscriber)
|
53
53
|
if defined?(ActiveSupport::Cache::Store)
|
54
54
|
ActiveSupport::Cache::Store.instrument = true
|
55
|
-
|
55
|
+
UnionStationExtension.attach_to(:active_support, subscriber)
|
56
56
|
end
|
57
57
|
PhusionPassenger.on_event(:starting_request_handler_thread) do
|
58
58
|
if defined?(ActiveSupport::Cache::Store)
|
@@ -70,7 +70,9 @@ class AnalyticsLogging < ActiveSupport::LogSubscriber
|
|
70
70
|
if defined?(Rails)
|
71
71
|
Rails.application.middleware.insert_after(
|
72
72
|
exceptions_middleware,
|
73
|
-
ExceptionLogger,
|
73
|
+
ExceptionLogger,
|
74
|
+
union_station_core,
|
75
|
+
app_group_name)
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
@@ -95,21 +97,18 @@ class AnalyticsLogging < ActiveSupport::LogSubscriber
|
|
95
97
|
end
|
96
98
|
|
97
99
|
def process_action(event)
|
98
|
-
|
99
|
-
if
|
100
|
-
view_runtime
|
101
|
-
log.message("View rendering time: #{(view_runtime * 1000).to_i}") if view_runtime
|
100
|
+
view_runtime = event.payload[:view_runtime]
|
101
|
+
if view_runtime
|
102
|
+
PhusionPassenger.log_total_view_rendering_time(nil, (view_runtime * 1000).to_i)
|
102
103
|
end
|
103
104
|
end
|
104
105
|
|
105
106
|
def sql(event)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
event.time, event.end, "#{name}\n#{sql}")
|
112
|
-
end
|
107
|
+
PhusionPassenger.log_database_query(nil,
|
108
|
+
event.payload[:name] || "SQL",
|
109
|
+
event.time,
|
110
|
+
event.end,
|
111
|
+
event.payload[:sql])
|
113
112
|
end
|
114
113
|
|
115
114
|
def cache_read(event)
|
@@ -130,76 +129,45 @@ class AnalyticsLogging < ActiveSupport::LogSubscriber
|
|
130
129
|
end
|
131
130
|
|
132
131
|
class ExceptionLogger
|
133
|
-
def initialize(app,
|
132
|
+
def initialize(app, union_station_core, app_group_name)
|
134
133
|
@app = app
|
135
|
-
@
|
134
|
+
@union_station_core = union_station_core
|
136
135
|
@app_group_name = app_group_name
|
137
136
|
end
|
138
137
|
|
139
138
|
def call(env)
|
140
139
|
@app.call(env)
|
141
140
|
rescue Exception => e
|
142
|
-
|
141
|
+
log_union_station_exception(env, e) if env[PASSENGER_TXN_ID]
|
143
142
|
raise e
|
144
143
|
end
|
145
144
|
|
146
145
|
private
|
147
|
-
def
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
request = ActionDispatch::Request.new(env)
|
154
|
-
if request.parameters['controller']
|
155
|
-
controller = request.parameters['controller'].humanize + "Controller"
|
156
|
-
action = request.parameters['action']
|
157
|
-
end
|
158
|
-
|
159
|
-
request_txn_id = env[PASSENGER_TXN_ID]
|
160
|
-
message = exception.message
|
161
|
-
message = exception.to_s if message.empty?
|
162
|
-
message = [message].pack('m')
|
163
|
-
message.gsub!("\n", "")
|
164
|
-
backtrace_string = [exception.backtrace.join("\n")].pack('m')
|
165
|
-
backtrace_string.gsub!("\n", "")
|
166
|
-
if action && controller
|
167
|
-
controller_action = "#{controller}##{action}"
|
168
|
-
else
|
169
|
-
controller_action = controller
|
170
|
-
end
|
171
|
-
|
172
|
-
log.message("Request transaction ID: #{request_txn_id}")
|
173
|
-
log.message("Message: #{message}")
|
174
|
-
log.message("Class: #{exception.class.name}")
|
175
|
-
log.message("Backtrace: #{backtrace_string}")
|
176
|
-
log.message("Controller action: #{controller_action}") if controller_action
|
177
|
-
ensure
|
178
|
-
log.close
|
146
|
+
def log_union_station_exception(env, exception)
|
147
|
+
options = {}
|
148
|
+
request = ActionDispatch::Request.new(env)
|
149
|
+
if request.parameters['controller']
|
150
|
+
options[:controller_name] = request.parameters['controller'].humanize + "Controller"
|
151
|
+
options[:action_name] = request.parameters['action']
|
179
152
|
end
|
153
|
+
PhusionPassenger.log_request_exception(env, exception, options)
|
180
154
|
end
|
181
155
|
end
|
182
156
|
|
183
157
|
module ACExtension
|
184
158
|
def process_action(action, *args)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
else
|
159
|
+
options = {
|
160
|
+
:controller_name => self.class.name,
|
161
|
+
:action_name => action_name,
|
162
|
+
:method => request.request_method
|
163
|
+
}
|
164
|
+
PhusionPassenger.log_controller_action(request.env, options) do
|
192
165
|
super
|
193
166
|
end
|
194
167
|
end
|
195
168
|
|
196
169
|
def render(*args)
|
197
|
-
|
198
|
-
if log
|
199
|
-
log.measure("view rendering") do
|
200
|
-
super
|
201
|
-
end
|
202
|
-
else
|
170
|
+
PhusionPassenger.log_view_rendering(request.env) do
|
203
171
|
super
|
204
172
|
end
|
205
173
|
end
|
@@ -207,14 +175,7 @@ class AnalyticsLogging < ActiveSupport::LogSubscriber
|
|
207
175
|
|
208
176
|
module ASBenchmarkableExtension
|
209
177
|
def benchmark_with_passenger(message = "Benchmarking", *args)
|
210
|
-
|
211
|
-
if log
|
212
|
-
log.measure("BENCHMARK: #{message}") do
|
213
|
-
benchmark_without_passenger(message, *args) do
|
214
|
-
yield
|
215
|
-
end
|
216
|
-
end
|
217
|
-
else
|
178
|
+
PhusionPassenger.benchmark(nil, message) do
|
218
179
|
benchmark_without_passenger(message, *args) do
|
219
180
|
yield
|
220
181
|
end
|
@@ -222,7 +183,7 @@ class AnalyticsLogging < ActiveSupport::LogSubscriber
|
|
222
183
|
end
|
223
184
|
end
|
224
185
|
|
225
|
-
|
186
|
+
private
|
226
187
|
def install_event_preprocessor(event_preprocessor)
|
227
188
|
public_methods(false).each do |name|
|
228
189
|
singleton = class << self; self end
|
@@ -232,7 +193,7 @@ class AnalyticsLogging < ActiveSupport::LogSubscriber
|
|
232
193
|
end)
|
233
194
|
end
|
234
195
|
end
|
235
|
-
end # class
|
196
|
+
end # class UnionStationExtension
|
236
197
|
end # module ActiveSupport3Extensions
|
237
198
|
|
238
199
|
end # module PhusionPassenger
|
@@ -22,8 +22,10 @@
|
|
22
22
|
# THE SOFTWARE.
|
23
23
|
|
24
24
|
module PhusionPassenger
|
25
|
-
|
25
|
+
UNION_STATION_CORE = "UNION_STATION_CORE".freeze
|
26
|
+
UNION_STATION_REQUEST_TRANSACTION = "UNION_STATION_REQUEST_TRANSACTION".freeze
|
26
27
|
PASSENGER_TXN_ID = "PASSENGER_TXN_ID".freeze
|
28
|
+
PASSENGER_APP_GROUP_NAME = "PASSENGER_APP_GROUP_NAME".freeze
|
27
29
|
PASSENGER_UNION_STATION_KEY = "UNION_STATION_KEY".freeze
|
28
30
|
RACK_HIJACK_IO = "rack.hijack_io".freeze
|
29
31
|
|
@@ -128,6 +128,11 @@ module LoaderSharedHelpers
|
|
128
128
|
if defined?(Gem)
|
129
129
|
File.open("#{dir}/ruby_info", "a") do |f|
|
130
130
|
f.puts "RubyGems version = #{Gem::VERSION}"
|
131
|
+
if Gem.respond_to?(:path)
|
132
|
+
f.puts "RubyGems paths = #{Gem.path.inspect}"
|
133
|
+
else
|
134
|
+
f.puts "RubyGems paths = unknown; incompatible RubyGems API"
|
135
|
+
end
|
131
136
|
end
|
132
137
|
File.open("#{dir}/activated_gems", "wb") do |f|
|
133
138
|
if Gem.respond_to?(:loaded_specs)
|
@@ -190,9 +195,9 @@ module LoaderSharedHelpers
|
|
190
195
|
def before_loading_app_code_step1(startup_file, options)
|
191
196
|
DebugLogging.log_level = options["log_level"] if options["log_level"]
|
192
197
|
|
193
|
-
# Instantiate the
|
194
|
-
PhusionPassenger.require_passenger_lib '
|
195
|
-
options["
|
198
|
+
# Instantiate the Union Station core if requested. Can be nil.
|
199
|
+
PhusionPassenger.require_passenger_lib 'union_station/core'
|
200
|
+
options["union_station_core"] = UnionStation::Core.new_from_options(options)
|
196
201
|
end
|
197
202
|
|
198
203
|
def run_load_path_setup_code(options)
|
@@ -320,8 +325,8 @@ module LoaderSharedHelpers
|
|
320
325
|
$0 = options["process_title"] + ": " + options["app_group_name"]
|
321
326
|
end
|
322
327
|
|
323
|
-
if forked && options["
|
324
|
-
options["
|
328
|
+
if forked && options["union_station_core"]
|
329
|
+
options["union_station_core"].clear_connection
|
325
330
|
end
|
326
331
|
|
327
332
|
# If we were forked from a preloader process then clear or
|
@@ -66,6 +66,7 @@
|
|
66
66
|
# a dot (.e.g `upstream_config.pass_headers`) then the structure field will
|
67
67
|
# also not be auto-generated, because it is assumed to belong to an existing
|
68
68
|
# structure field.
|
69
|
+
# * post - The extra information needed by function for post-processing.
|
69
70
|
# * header - The name of the corresponding CGI header. By default CGI header
|
70
71
|
# generation code is automatically generated, using the configuration
|
71
72
|
# option's name in uppercase as the CGI header name.
|
@@ -193,7 +194,8 @@ LOCATION_CONFIGURATION_OPTIONS = [
|
|
193
194
|
:name => 'passenger_ignore_headers',
|
194
195
|
:take => 'NGX_CONF_1MORE',
|
195
196
|
:function => 'ngx_conf_set_bitmask_slot',
|
196
|
-
:field => 'upstream_config.ignore_headers'
|
197
|
+
:field => 'upstream_config.ignore_headers',
|
198
|
+
:post => '&ngx_http_upstream_ignore_headers_masks'
|
197
199
|
},
|
198
200
|
{
|
199
201
|
:name => 'passenger_set_cgi_param',
|
@@ -57,21 +57,108 @@ class << self
|
|
57
57
|
@@advertised_concurrency_level = value
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
61
|
-
|
62
|
-
if
|
63
|
-
|
60
|
+
def measure_and_log_event(env, name)
|
61
|
+
transaction = lookup_union_station_web_transaction(env)
|
62
|
+
if transaction
|
63
|
+
transaction.measure(name) do
|
64
64
|
yield
|
65
65
|
end
|
66
66
|
else
|
67
67
|
yield
|
68
68
|
end
|
69
69
|
end
|
70
|
+
|
71
|
+
def benchmark(env = nil, title = "Benchmarking", &block)
|
72
|
+
measure_and_log_event(env, "BENCHMARK: #{title}", &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Log an exception that occurred during a request.
|
76
|
+
def log_request_exception(env, exception, options = nil)
|
77
|
+
return if !env[PASSENGER_TXN_ID]
|
78
|
+
core = lookup_union_station_core(env)
|
79
|
+
if core
|
80
|
+
transaction = core.new_transaction(
|
81
|
+
env[PASSENGER_APP_GROUP_NAME],
|
82
|
+
:exceptions,
|
83
|
+
env[PASSENGER_UNION_STATION_KEY])
|
84
|
+
begin
|
85
|
+
request_txn_id = env[PASSENGER_TXN_ID]
|
86
|
+
message = exception.message
|
87
|
+
message = exception.to_s if message.empty?
|
88
|
+
message = [message].pack('m')
|
89
|
+
message.gsub!("\n", "")
|
90
|
+
backtrace_string = [exception.backtrace.join("\n")].pack('m')
|
91
|
+
backtrace_string.gsub!("\n", "")
|
92
|
+
|
93
|
+
transaction.message("Request transaction ID: #{request_txn_id}")
|
94
|
+
transaction.message("Message: #{message}")
|
95
|
+
transaction.message("Class: #{exception.class.name}")
|
96
|
+
transaction.message("Backtrace: #{backtrace_string}")
|
97
|
+
|
98
|
+
if options && options[:controller_name]
|
99
|
+
if options[:action_name]
|
100
|
+
controller_action = "#{options[:controller_name]}##{options[:action_name]}"
|
101
|
+
else
|
102
|
+
controller_action = controller_name
|
103
|
+
end
|
104
|
+
transaction.message("Controller action: #{controller_action}")
|
105
|
+
end
|
106
|
+
ensure
|
107
|
+
transaction.close
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Log a controller action invocation.
|
113
|
+
def log_controller_action(env, options)
|
114
|
+
transaction = lookup_union_station_web_transaction(env)
|
115
|
+
if transaction
|
116
|
+
if options[:controller_name]
|
117
|
+
if !options[:action_name]
|
118
|
+
raise ArgumentError, "The :action_name option must be set"
|
119
|
+
end
|
120
|
+
transaction.message("Controller action: #{options[:controller_name]}##{options[:action_name]}")
|
121
|
+
end
|
122
|
+
if options[:method]
|
123
|
+
transaction.message("Request method: #{options[:method]}")
|
124
|
+
end
|
125
|
+
transaction.measure("framework request processing") do
|
126
|
+
yield
|
127
|
+
end
|
128
|
+
else
|
129
|
+
yield
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Log the total view rendering time of a request.
|
134
|
+
def log_total_view_rendering_time(env, runtime)
|
135
|
+
transaction = lookup_union_station_web_transaction(env)
|
136
|
+
if transaction
|
137
|
+
transaction.message("View rendering time: #{(runtime).to_i}")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Log a single view rendering.
|
142
|
+
def log_view_rendering(env = nil, &block)
|
143
|
+
measure_and_log_event(env, "view rendering", &block)
|
144
|
+
end
|
70
145
|
|
146
|
+
# Log a database query.
|
147
|
+
def log_database_query(env, name, begin_time, end_time, sql)
|
148
|
+
transaction = lookup_union_station_web_transaction(env)
|
149
|
+
if transaction
|
150
|
+
digest = Digest::MD5.hexdigest("#{name}\0#{sql}\0#{rand}")
|
151
|
+
transaction.measured_time_points("DB BENCHMARK: #{digest}",
|
152
|
+
begin_time,
|
153
|
+
end_time,
|
154
|
+
"#{name}\n#{sql}")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
71
158
|
def log_cache_hit(env, name)
|
72
|
-
|
73
|
-
if
|
74
|
-
|
159
|
+
transaction = lookup_union_station_web_transaction(env)
|
160
|
+
if transaction
|
161
|
+
transaction.message("Cache hit: #{name}")
|
75
162
|
return true
|
76
163
|
else
|
77
164
|
return false
|
@@ -79,12 +166,12 @@ class << self
|
|
79
166
|
end
|
80
167
|
|
81
168
|
def log_cache_miss(env, name, generation_time = nil)
|
82
|
-
|
83
|
-
if
|
169
|
+
transaction = lookup_union_station_web_transaction(env)
|
170
|
+
if transaction
|
84
171
|
if generation_time
|
85
|
-
|
172
|
+
transaction.message("Cache miss (#{generation_time.to_i}): #{name}")
|
86
173
|
else
|
87
|
-
|
174
|
+
transaction.message("Cache miss: #{name}")
|
88
175
|
end
|
89
176
|
return true
|
90
177
|
else
|
@@ -111,14 +198,19 @@ private
|
|
111
198
|
raise ArgumentError, "Unknown event name '#{name}'"
|
112
199
|
end
|
113
200
|
end
|
114
|
-
|
115
|
-
def
|
201
|
+
|
202
|
+
def lookup_union_station_core(env = nil)
|
116
203
|
if env
|
117
|
-
|
118
|
-
else
|
119
|
-
return Thread.current[PASSENGER_ANALYTICS_WEB_LOG]
|
204
|
+
result = env[UNION_STATION_CORE]
|
120
205
|
end
|
206
|
+
return result || Thread.current[UNION_STATION_CORE]
|
121
207
|
end
|
122
208
|
|
209
|
+
def lookup_union_station_web_transaction(env = nil)
|
210
|
+
if env
|
211
|
+
result = env[UNION_STATION_REQUEST_TRANSACTION]
|
212
|
+
end
|
213
|
+
return result || Thread.current[UNION_STATION_REQUEST_TRANSACTION]
|
214
|
+
end
|
123
215
|
end
|
124
216
|
end # module PhusionPassenger
|