puma 5.6.4 → 6.4.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +372 -6
- data/LICENSE +0 -0
- data/README.md +79 -29
- data/bin/puma-wild +1 -1
- data/docs/architecture.md +0 -0
- data/docs/compile_options.md +34 -0
- data/docs/deployment.md +0 -0
- data/docs/fork_worker.md +1 -3
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +0 -0
- data/docs/jungle/rc.d/README.md +0 -0
- data/docs/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +12 -0
- data/docs/nginx.md +1 -1
- data/docs/plugins.md +0 -0
- data/docs/rails_dev_mode.md +0 -0
- data/docs/restart.md +1 -0
- data/docs/signals.md +0 -0
- data/docs/stats.md +0 -0
- data/docs/systemd.md +3 -6
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/ext_help.h +0 -0
- data/ext/puma_http11/extconf.rb +22 -10
- data/ext/puma_http11/http11_parser.c +1 -1
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +2 -2
- data/ext/puma_http11/http11_parser.rl +2 -2
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +153 -27
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +167 -65
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +7 -4
- data/lib/puma/binder.rb +51 -54
- data/lib/puma/cli.rb +16 -18
- data/lib/puma/client.rb +100 -26
- data/lib/puma/cluster/worker.rb +18 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +102 -40
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +77 -59
- data/lib/puma/const.rb +129 -92
- data/lib/puma/control_cli.rb +33 -23
- data/lib/puma/detect.rb +7 -4
- data/lib/puma/dsl.rb +251 -53
- data/lib/puma/error_logger.rb +18 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +39 -4
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/json_serialization.rb +0 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +113 -175
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +26 -12
- data/lib/puma/minissl.rb +113 -15
- data/lib/puma/null_io.rb +21 -2
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/plugin.rb +0 -0
- data/lib/puma/rack/builder.rb +6 -6
- data/lib/puma/rack/urlmap.rb +1 -1
- data/lib/puma/rack_default.rb +19 -4
- data/lib/puma/reactor.rb +19 -10
- data/lib/puma/request.rb +365 -166
- data/lib/puma/runner.rb +56 -20
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +137 -87
- data/lib/puma/single.rb +13 -11
- data/lib/puma/state_file.rb +4 -6
- data/lib/puma/thread_pool.rb +57 -19
- data/lib/puma/util.rb +12 -14
- data/lib/puma.rb +12 -11
- data/lib/rack/handler/puma.rb +113 -86
- data/tools/Dockerfile +2 -2
- data/tools/trickletest.rb +0 -0
- metadata +11 -6
- data/lib/puma/queue_close.rb +0 -26
- data/lib/puma/systemd.rb +0 -46
data/lib/puma/cluster/worker.rb
CHANGED
@@ -2,27 +2,29 @@
|
|
2
2
|
|
3
3
|
module Puma
|
4
4
|
class Cluster < Puma::Runner
|
5
|
+
#—————————————————————— DO NOT USE — this class is for internal use only ———
|
6
|
+
|
7
|
+
|
5
8
|
# This class is instantiated by the `Puma::Cluster` and represents a single
|
6
9
|
# worker process.
|
7
10
|
#
|
8
11
|
# At the core of this class is running an instance of `Puma::Server` which
|
9
12
|
# gets created via the `start_server` method from the `Puma::Runner` class
|
10
13
|
# that this inherits from.
|
11
|
-
class Worker < Puma::Runner
|
14
|
+
class Worker < Puma::Runner # :nodoc:
|
12
15
|
attr_reader :index, :master
|
13
16
|
|
14
17
|
def initialize(index:, master:, launcher:, pipes:, server: nil)
|
15
|
-
super
|
18
|
+
super(launcher)
|
16
19
|
|
17
20
|
@index = index
|
18
21
|
@master = master
|
19
|
-
@launcher = launcher
|
20
|
-
@options = launcher.options
|
21
22
|
@check_pipe = pipes[:check_pipe]
|
22
23
|
@worker_write = pipes[:worker_write]
|
23
24
|
@fork_pipe = pipes[:fork_pipe]
|
24
25
|
@wakeup = pipes[:wakeup]
|
25
26
|
@server = server
|
27
|
+
@hook_data = {}
|
26
28
|
end
|
27
29
|
|
28
30
|
def run
|
@@ -52,13 +54,14 @@ module Puma
|
|
52
54
|
|
53
55
|
# Invoke any worker boot hooks so they can get
|
54
56
|
# things in shape before booting the app.
|
55
|
-
@
|
57
|
+
@config.run_hooks(:before_worker_boot, index, @log_writer, @hook_data)
|
56
58
|
|
57
59
|
begin
|
58
60
|
server = @server ||= start_server
|
59
61
|
rescue Exception => e
|
60
62
|
log "! Unable to start worker"
|
61
|
-
log e
|
63
|
+
log e
|
64
|
+
log e.backtrace.join("\n ")
|
62
65
|
exit 1
|
63
66
|
end
|
64
67
|
|
@@ -83,8 +86,7 @@ module Puma
|
|
83
86
|
if restart_server.length > 0
|
84
87
|
restart_server.clear
|
85
88
|
server.begin_restart(true)
|
86
|
-
@
|
87
|
-
Puma::Util.nakayoshi_gc @events if @options[:nakayoshi_fork]
|
89
|
+
@config.run_hooks(:before_refork, nil, @log_writer, @hook_data)
|
88
90
|
end
|
89
91
|
elsif idx == 0 # restart server
|
90
92
|
restart_server << true << false
|
@@ -113,6 +115,11 @@ module Puma
|
|
113
115
|
|
114
116
|
while restart_server.pop
|
115
117
|
server_thread = server.run
|
118
|
+
|
119
|
+
if @log_writer.debug? && index == 0
|
120
|
+
debug_loaded_extensions "Loaded Extensions - worker 0:"
|
121
|
+
end
|
122
|
+
|
116
123
|
stat_thread ||= Thread.new(@worker_write) do |io|
|
117
124
|
Puma.set_thread_name "stat pld"
|
118
125
|
base_payload = "p#{Process.pid}"
|
@@ -138,7 +145,7 @@ module Puma
|
|
138
145
|
|
139
146
|
# Invoke any worker shutdown hooks so they can prevent the worker
|
140
147
|
# exiting until any background operations are completed
|
141
|
-
@
|
148
|
+
@config.run_hooks(:before_worker_shutdown, index, @log_writer, @hook_data)
|
142
149
|
ensure
|
143
150
|
@worker_write << "t#{Process.pid}\n" rescue nil
|
144
151
|
@worker_write.close
|
@@ -147,7 +154,7 @@ module Puma
|
|
147
154
|
private
|
148
155
|
|
149
156
|
def spawn_worker(idx)
|
150
|
-
@
|
157
|
+
@config.run_hooks(:before_worker_fork, idx, @log_writer, @hook_data)
|
151
158
|
|
152
159
|
pid = fork do
|
153
160
|
new_worker = Worker.new index: idx,
|
@@ -165,7 +172,7 @@ module Puma
|
|
165
172
|
exit! 1
|
166
173
|
end
|
167
174
|
|
168
|
-
@
|
175
|
+
@config.run_hooks(:after_worker_fork, idx, @log_writer, @hook_data)
|
169
176
|
pid
|
170
177
|
end
|
171
178
|
end
|
@@ -2,12 +2,15 @@
|
|
2
2
|
|
3
3
|
module Puma
|
4
4
|
class Cluster < Runner
|
5
|
+
#—————————————————————— DO NOT USE — this class is for internal use only ———
|
6
|
+
|
7
|
+
|
5
8
|
# This class represents a worker process from the perspective of the puma
|
6
9
|
# master process. It contains information about the process and its health
|
7
10
|
# and it exposes methods to control the process via IPC. It does not
|
8
11
|
# include the actual logic executed by the worker process itself. For that,
|
9
12
|
# see Puma::Cluster::Worker.
|
10
|
-
class WorkerHandle
|
13
|
+
class WorkerHandle # :nodoc:
|
11
14
|
def initialize(idx, pid, phase, options)
|
12
15
|
@index = idx
|
13
16
|
@pid = pid
|
data/lib/puma/cluster.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
require 'time'
|
3
|
+
require_relative 'runner'
|
4
|
+
require_relative 'util'
|
5
|
+
require_relative 'plugin'
|
6
|
+
require_relative 'cluster/worker_handle'
|
7
|
+
require_relative 'cluster/worker'
|
10
8
|
|
11
9
|
module Puma
|
12
10
|
# This class is instantiated by the `Puma::Launcher` and used
|
@@ -17,8 +15,8 @@ module Puma
|
|
17
15
|
# via the `spawn_workers` method call. Each worker will have it's own
|
18
16
|
# instance of a `Puma::Server`.
|
19
17
|
class Cluster < Runner
|
20
|
-
def initialize(
|
21
|
-
super
|
18
|
+
def initialize(launcher)
|
19
|
+
super(launcher)
|
22
20
|
|
23
21
|
@phase = 0
|
24
22
|
@workers = []
|
@@ -27,6 +25,10 @@ module Puma
|
|
27
25
|
@phased_restart = false
|
28
26
|
end
|
29
27
|
|
28
|
+
# Returns the list of cluster worker handles.
|
29
|
+
# @return [Array<Puma::Cluster::WorkerHandle>]
|
30
|
+
attr_reader :workers
|
31
|
+
|
30
32
|
def stop_workers
|
31
33
|
log "- Gracefully shutting down workers..."
|
32
34
|
@workers.each { |x| x.term }
|
@@ -83,16 +85,14 @@ module Puma
|
|
83
85
|
@workers << WorkerHandle.new(idx, pid, @phase, @options)
|
84
86
|
end
|
85
87
|
|
86
|
-
if @options[:fork_worker] &&
|
87
|
-
@workers.all? {|x| x.phase == @phase}
|
88
|
-
|
88
|
+
if @options[:fork_worker] && all_workers_in_phase?
|
89
89
|
@fork_writer << "0\n"
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
93
|
# @version 5.0.0
|
94
94
|
def spawn_worker(idx, master)
|
95
|
-
@
|
95
|
+
@config.run_hooks(:before_worker_fork, idx, @log_writer)
|
96
96
|
|
97
97
|
pid = fork { worker(idx, master) }
|
98
98
|
if !pid
|
@@ -101,7 +101,7 @@ module Puma
|
|
101
101
|
exit! 1
|
102
102
|
end
|
103
103
|
|
104
|
-
@
|
104
|
+
@config.run_hooks(:after_worker_fork, idx, @log_writer)
|
105
105
|
pid
|
106
106
|
end
|
107
107
|
|
@@ -146,10 +146,22 @@ module Puma
|
|
146
146
|
idx
|
147
147
|
end
|
148
148
|
|
149
|
+
def worker_at(idx)
|
150
|
+
@workers.find { |w| w.index == idx }
|
151
|
+
end
|
152
|
+
|
149
153
|
def all_workers_booted?
|
150
154
|
@workers.count { |w| !w.booted? } == 0
|
151
155
|
end
|
152
156
|
|
157
|
+
def all_workers_in_phase?
|
158
|
+
@workers.all? { |w| w.phase == @phase }
|
159
|
+
end
|
160
|
+
|
161
|
+
def all_workers_idle_timed_out?
|
162
|
+
(@workers.map(&:pid) - idle_timed_out_worker_pids).empty?
|
163
|
+
end
|
164
|
+
|
153
165
|
def check_workers
|
154
166
|
return if @next_check >= Time.now
|
155
167
|
|
@@ -176,10 +188,10 @@ module Puma
|
|
176
188
|
end
|
177
189
|
end
|
178
190
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
].compact.min
|
191
|
+
t = @workers.reject(&:term?)
|
192
|
+
t.map!(&:ping_timeout)
|
193
|
+
|
194
|
+
@next_check = [t.min, @next_check].compact.min
|
183
195
|
end
|
184
196
|
|
185
197
|
def worker(index, master)
|
@@ -209,8 +221,8 @@ module Puma
|
|
209
221
|
stop
|
210
222
|
end
|
211
223
|
|
212
|
-
def phased_restart
|
213
|
-
return false if @options[:preload_app]
|
224
|
+
def phased_restart(refork = false)
|
225
|
+
return false if @options[:preload_app] && !refork
|
214
226
|
|
215
227
|
@phased_restart = true
|
216
228
|
wakeup!
|
@@ -226,7 +238,7 @@ module Puma
|
|
226
238
|
def stop_blocked
|
227
239
|
@status = :stop if @status == :run
|
228
240
|
wakeup!
|
229
|
-
@control
|
241
|
+
@control&.stop true
|
230
242
|
Process.waitall
|
231
243
|
end
|
232
244
|
|
@@ -248,24 +260,24 @@ module Puma
|
|
248
260
|
old_worker_count = @workers.count { |w| w.phase != @phase }
|
249
261
|
worker_status = @workers.map do |w|
|
250
262
|
{
|
251
|
-
started_at: w.started_at
|
263
|
+
started_at: utc_iso8601(w.started_at),
|
252
264
|
pid: w.pid,
|
253
265
|
index: w.index,
|
254
266
|
phase: w.phase,
|
255
267
|
booted: w.booted?,
|
256
|
-
last_checkin: w.last_checkin
|
268
|
+
last_checkin: utc_iso8601(w.last_checkin),
|
257
269
|
last_status: w.last_status,
|
258
270
|
}
|
259
271
|
end
|
260
272
|
|
261
273
|
{
|
262
|
-
started_at: @started_at
|
274
|
+
started_at: utc_iso8601(@started_at),
|
263
275
|
workers: @workers.size,
|
264
276
|
phase: @phase,
|
265
277
|
booted_workers: worker_status.count { |w| w[:booted] },
|
266
278
|
old_workers: old_worker_count,
|
267
279
|
worker_status: worker_status,
|
268
|
-
}
|
280
|
+
}.merge(super)
|
269
281
|
end
|
270
282
|
|
271
283
|
def preload?
|
@@ -274,10 +286,10 @@ module Puma
|
|
274
286
|
|
275
287
|
# @version 5.0.0
|
276
288
|
def fork_worker!
|
277
|
-
if (worker =
|
289
|
+
if (worker = worker_at 0)
|
278
290
|
worker.phase += 1
|
279
291
|
end
|
280
|
-
phased_restart
|
292
|
+
phased_restart(true)
|
281
293
|
end
|
282
294
|
|
283
295
|
# We do this in a separate method to keep the lambda scope
|
@@ -290,7 +302,7 @@ module Puma
|
|
290
302
|
|
291
303
|
# Auto-fork after the specified number of requests.
|
292
304
|
if (fork_requests = @options[:fork_worker].to_i) > 0
|
293
|
-
@
|
305
|
+
@events.register(:ping!) do |w|
|
294
306
|
fork_worker! if w.index == 0 &&
|
295
307
|
w.phase == 0 &&
|
296
308
|
w.last_status[:requests_count] >= fork_requests
|
@@ -336,6 +348,8 @@ module Puma
|
|
336
348
|
def run
|
337
349
|
@status = :run
|
338
350
|
|
351
|
+
@idle_workers = {}
|
352
|
+
|
339
353
|
output_header "cluster"
|
340
354
|
|
341
355
|
# This is aligned with the output from Runner, see Runner#output_header
|
@@ -372,12 +386,12 @@ module Puma
|
|
372
386
|
else
|
373
387
|
log "* Restarts: (\u2714) hot (\u2714) phased"
|
374
388
|
|
375
|
-
unless @
|
389
|
+
unless @config.app_configured?
|
376
390
|
error "No application configured, nothing to run"
|
377
391
|
exit 1
|
378
392
|
end
|
379
393
|
|
380
|
-
@launcher.binder.parse @options[:binds]
|
394
|
+
@launcher.binder.parse @options[:binds]
|
381
395
|
end
|
382
396
|
|
383
397
|
read, @wakeup = Puma::Util.pipe
|
@@ -409,8 +423,9 @@ module Puma
|
|
409
423
|
|
410
424
|
@master_read, @worker_write = read, @wakeup
|
411
425
|
|
412
|
-
@
|
413
|
-
|
426
|
+
@options[:worker_write] = @worker_write
|
427
|
+
|
428
|
+
@config.run_hooks(:before_fork, nil, @log_writer)
|
414
429
|
|
415
430
|
spawn_workers
|
416
431
|
|
@@ -425,6 +440,11 @@ module Puma
|
|
425
440
|
|
426
441
|
while @status == :run
|
427
442
|
begin
|
443
|
+
if all_workers_idle_timed_out?
|
444
|
+
log "- All workers reached idle timeout"
|
445
|
+
break
|
446
|
+
end
|
447
|
+
|
428
448
|
if @phased_restart
|
429
449
|
start_phased_restart
|
430
450
|
@phased_restart = false
|
@@ -445,7 +465,7 @@ module Puma
|
|
445
465
|
|
446
466
|
if req == "b" || req == "f"
|
447
467
|
pid, idx = result.split(':').map(&:to_i)
|
448
|
-
w =
|
468
|
+
w = worker_at idx
|
449
469
|
w.pid = pid if w.pid.nil?
|
450
470
|
end
|
451
471
|
|
@@ -462,22 +482,37 @@ module Puma
|
|
462
482
|
when "t"
|
463
483
|
w.term unless w.term?
|
464
484
|
when "p"
|
465
|
-
|
466
|
-
|
485
|
+
status = result.sub(/^\d+/,'').chomp
|
486
|
+
w.ping!(status)
|
487
|
+
@events.fire(:ping!, w)
|
488
|
+
|
489
|
+
if in_phased_restart && workers_not_booted.positive? && w0 = worker_at(0)
|
490
|
+
w0.ping!(status)
|
491
|
+
@events.fire(:ping!, w0)
|
492
|
+
end
|
493
|
+
|
467
494
|
if !booted && @workers.none? {|worker| worker.last_status.empty?}
|
468
|
-
@
|
495
|
+
@events.fire_on_booted!
|
496
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
469
497
|
booted = true
|
470
498
|
end
|
499
|
+
when "i"
|
500
|
+
if @idle_workers[pid]
|
501
|
+
@idle_workers.delete pid
|
502
|
+
else
|
503
|
+
@idle_workers[pid] = true
|
504
|
+
end
|
471
505
|
end
|
472
506
|
else
|
473
507
|
log "! Out-of-sync worker list, no #{pid} worker"
|
474
508
|
end
|
475
509
|
end
|
510
|
+
|
476
511
|
if in_phased_restart && workers_not_booted.zero?
|
477
512
|
@events.fire_on_booted!
|
513
|
+
debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
|
478
514
|
in_phased_restart = false
|
479
515
|
end
|
480
|
-
|
481
516
|
rescue Interrupt
|
482
517
|
@status = :stop
|
483
518
|
end
|
@@ -506,10 +541,28 @@ module Puma
|
|
506
541
|
# loops thru @workers, removing workers that exited, and calling
|
507
542
|
# `#term` if needed
|
508
543
|
def wait_workers
|
544
|
+
# Reap all children, known workers or otherwise.
|
545
|
+
# If puma has PID 1, as it's common in containerized environments,
|
546
|
+
# then it's responsible for reaping orphaned processes, so we must reap
|
547
|
+
# all our dead children, regardless of whether they are workers we spawned
|
548
|
+
# or some reattached processes.
|
549
|
+
reaped_children = {}
|
550
|
+
loop do
|
551
|
+
begin
|
552
|
+
pid, status = Process.wait2(-1, Process::WNOHANG)
|
553
|
+
break unless pid
|
554
|
+
reaped_children[pid] = status
|
555
|
+
rescue Errno::ECHILD
|
556
|
+
break
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
509
560
|
@workers.reject! do |w|
|
510
561
|
next false if w.pid.nil?
|
511
562
|
begin
|
512
|
-
|
563
|
+
# When `fork_worker` is enabled, some worker may not be direct children, but grand children.
|
564
|
+
# Because of this they won't be reaped by `Process.wait2(-1)`, so we need to check them individually)
|
565
|
+
if reaped_children.delete(w.pid) || (@options[:fork_worker] && Process.wait(w.pid, Process::WNOHANG))
|
513
566
|
true
|
514
567
|
else
|
515
568
|
w.term if w.term?
|
@@ -526,6 +579,11 @@ module Puma
|
|
526
579
|
end
|
527
580
|
end
|
528
581
|
end
|
582
|
+
|
583
|
+
# Log unknown children
|
584
|
+
reaped_children.each do |pid, status|
|
585
|
+
log "! reaped unknown child process pid=#{pid} status=#{status}"
|
586
|
+
end
|
529
587
|
end
|
530
588
|
|
531
589
|
# @version 5.0.0
|
@@ -533,14 +591,18 @@ module Puma
|
|
533
591
|
@workers.each do |w|
|
534
592
|
if !w.term? && w.ping_timeout <= Time.now
|
535
593
|
details = if w.booted?
|
536
|
-
"(
|
594
|
+
"(Worker #{w.index} failed to check in within #{@options[:worker_timeout]} seconds)"
|
537
595
|
else
|
538
|
-
"(
|
596
|
+
"(Worker #{w.index} failed to boot within #{@options[:worker_boot_timeout]} seconds)"
|
539
597
|
end
|
540
598
|
log "! Terminating timed out worker #{details}: #{w.pid}"
|
541
599
|
w.kill
|
542
600
|
end
|
543
601
|
end
|
544
602
|
end
|
603
|
+
|
604
|
+
def idle_timed_out_worker_pids
|
605
|
+
@idle_workers.keys
|
606
|
+
end
|
545
607
|
end
|
546
608
|
end
|
data/lib/puma/commonlogger.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Puma
|
4
4
|
# Rack::CommonLogger forwards every request to the given +app+, and
|
5
5
|
# logs a line in the
|
6
|
-
# {Apache common log format}[https://httpd.apache.org/docs/
|
6
|
+
# {Apache common log format}[https://httpd.apache.org/docs/2.4/logs.html#common]
|
7
7
|
# to the +logger+.
|
8
8
|
#
|
9
9
|
# If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
|
@@ -16,7 +16,7 @@ module Puma
|
|
16
16
|
# (which is called without arguments in order to make the error appear for
|
17
17
|
# sure)
|
18
18
|
class CommonLogger
|
19
|
-
# Common Log Format: https://httpd.apache.org/docs/
|
19
|
+
# Common Log Format: https://httpd.apache.org/docs/2.4/logs.html#common
|
20
20
|
#
|
21
21
|
# lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
|
22
22
|
#
|
@@ -25,10 +25,17 @@ module Puma
|
|
25
25
|
|
26
26
|
HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
LOG_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S %z'
|
29
|
+
|
30
|
+
CONTENT_LENGTH = 'Content-Length' # should be lower case from app,
|
31
|
+
# Util::HeaderHash allows mixed
|
32
|
+
HTTP_VERSION = Const::HTTP_VERSION
|
33
|
+
HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
|
34
|
+
PATH_INFO = Const::PATH_INFO
|
35
|
+
QUERY_STRING = Const::QUERY_STRING
|
36
|
+
REMOTE_ADDR = Const::REMOTE_ADDR
|
37
|
+
REMOTE_USER = 'REMOTE_USER'
|
38
|
+
REQUEST_METHOD = Const::REQUEST_METHOD
|
32
39
|
|
33
40
|
def initialize(app, logger=nil)
|
34
41
|
@app = app
|
@@ -57,13 +64,13 @@ module Puma
|
|
57
64
|
now = Time.now
|
58
65
|
|
59
66
|
msg = HIJACK_FORMAT % [
|
60
|
-
env[
|
61
|
-
env[
|
62
|
-
now.strftime(
|
67
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
68
|
+
env[REMOTE_USER] || "-",
|
69
|
+
now.strftime(LOG_TIME_FORMAT),
|
63
70
|
env[REQUEST_METHOD],
|
64
71
|
env[PATH_INFO],
|
65
72
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
66
|
-
env[
|
73
|
+
env[HTTP_VERSION],
|
67
74
|
now - began_at ]
|
68
75
|
|
69
76
|
write(msg)
|
@@ -74,13 +81,13 @@ module Puma
|
|
74
81
|
length = extract_content_length(header)
|
75
82
|
|
76
83
|
msg = FORMAT % [
|
77
|
-
env[
|
78
|
-
env[
|
79
|
-
now.strftime(
|
84
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
|
85
|
+
env[REMOTE_USER] || "-",
|
86
|
+
now.strftime(LOG_TIME_FORMAT),
|
80
87
|
env[REQUEST_METHOD],
|
81
88
|
env[PATH_INFO],
|
82
89
|
env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
|
83
|
-
env[
|
90
|
+
env[HTTP_VERSION],
|
84
91
|
status.to_s[0..3],
|
85
92
|
length,
|
86
93
|
now - began_at ]
|