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