clogger RubyGem user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
* [PATCH 0/2] fixes for pure-Ruby users
@ 2015-02-27 22:45 Eric Wong
  2015-02-27 22:45 ` [PATCH 1/2] pure: fix reentrancy of request_time Eric Wong
  2015-02-27 22:45 ` [PATCH 2/2] pure: use monotonic clock if possible Eric Wong
  0 siblings, 2 replies; 3+ messages in thread
From: Eric Wong @ 2015-02-27 22:45 UTC (permalink / raw)
  To: clogger-public

These bugs were discovered by some folks who forgot to upgrade from
clogger 1.0.1 when when upgrading from MRI 1.9.3 to 2.1 and were
inadvertently using the pure Ruby version instead of the C extension.

New release coming, but does not affect users of the C extension.

Eric Wong (2):
      pure: fix reentrancy of request_time
      pure: use monotonic clock if possible


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] pure: fix reentrancy of request_time
  2015-02-27 22:45 [PATCH 0/2] fixes for pure-Ruby users Eric Wong
@ 2015-02-27 22:45 ` Eric Wong
  2015-02-27 22:45 ` [PATCH 2/2] pure: use monotonic clock if possible Eric Wong
  1 sibling, 0 replies; 3+ messages in thread
From: Eric Wong @ 2015-02-27 22:45 UTC (permalink / raw)
  To: clogger-public

For users unable to compile the C extension, multithreaded usage
of clogger could return invalid request time measurements.

This does not affect users of the C extension.
---
 lib/clogger/pure.rb | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/lib/clogger/pure.rb b/lib/clogger/pure.rb
index bb3fc16..9efb00c 100644
--- a/lib/clogger/pure.rb
+++ b/lib/clogger/pure.rb
@@ -6,7 +6,7 @@
 class Clogger
 
   attr_accessor :env, :status, :headers, :body
-  attr_writer :body_bytes_sent
+  attr_writer :body_bytes_sent, :start
 
   def initialize(app, opts = {})
     # trigger autoload to avoid thread-safety issues later on
@@ -28,10 +28,10 @@ def initialize(app, opts = {})
   end
 
   def call(env)
-    @start = Time.now
+    start = Time.now
     resp = @app.call(env)
     unless resp.instance_of?(Array) && resp.size == 3
-      log(env, 500, {})
+      log(env, 500, {}, start)
       raise TypeError, "app response not a 3 element Array: #{resp.inspect}"
     end
     status, headers, body = resp
@@ -39,13 +39,14 @@ def call(env)
     if @wrap_body
       @reentrant = env['rack.multithread'] if @reentrant.nil?
       wbody = @reentrant ? self.dup : self
+      wbody.start = start
       wbody.env = env
       wbody.status = status
       wbody.headers = headers
       wbody.body = body
       return [ status, headers, wbody ]
     end
-    log(env, status, headers)
+    log(env, status, headers, start)
     [ status, headers, body ]
   end
 
@@ -60,8 +61,8 @@ def each
 
   def close
     @body.close if @body.respond_to?(:close)
-    ensure
-      log(@env, @status, @headers)
+  ensure
+    log(@env, @status, @headers)
   end
 
   def reentrant?
@@ -153,7 +154,7 @@ def time_format(sec, usec, format, div)
     format % [ sec, usec / div ]
   end
 
-  def log(env, status, headers)
+  def log(env, status, headers, start = @start)
     str = @fmt_ops.map { |op|
       case op[0]
       when OP_LITERAL; op[1]
@@ -164,7 +165,7 @@ def log(env, status, headers)
       when OP_TIME_LOCAL; Time.now.strftime(op[1])
       when OP_TIME_UTC; Time.now.utc.strftime(op[1])
       when OP_REQUEST_TIME
-        t = Time.now - @start
+        t = Time.now - start
         time_format(t.to_i, (t - t.to_i) * 1000000, op[1], op[2])
       when OP_TIME
         t = Time.now
-- 
EW


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] pure: use monotonic clock if possible
  2015-02-27 22:45 [PATCH 0/2] fixes for pure-Ruby users Eric Wong
  2015-02-27 22:45 ` [PATCH 1/2] pure: fix reentrancy of request_time Eric Wong
@ 2015-02-27 22:45 ` Eric Wong
  1 sibling, 0 replies; 3+ messages in thread
From: Eric Wong @ 2015-02-27 22:45 UTC (permalink / raw)
  To: clogger-public

Ruby 2.1.0 and later exposes Process.clock_gettime, resulting
in less garbage and access to the monotonic clock if it is
available.  Try to use it to achieve feature parity with the
C extension (which has always used the monotonic clock if possible).
---
 lib/clogger/pure.rb | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/lib/clogger/pure.rb b/lib/clogger/pure.rb
index 9efb00c..5e7ccfe 100644
--- a/lib/clogger/pure.rb
+++ b/lib/clogger/pure.rb
@@ -28,7 +28,7 @@ def initialize(app, opts = {})
   end
 
   def call(env)
-    start = Time.now
+    start = mono_now
     resp = @app.call(env)
     unless resp.instance_of?(Array) && resp.size == 3
       log(env, 500, {}, start)
@@ -165,7 +165,7 @@ def log(env, status, headers, start = @start)
       when OP_TIME_LOCAL; Time.now.strftime(op[1])
       when OP_TIME_UTC; Time.now.utc.strftime(op[1])
       when OP_REQUEST_TIME
-        t = Time.now - start
+        t = mono_now - start
         time_format(t.to_i, (t - t.to_i) * 1000000, op[1], op[2])
       when OP_TIME
         t = Time.now
@@ -185,4 +185,14 @@ def log(env, status, headers, start = @start)
     end
     nil
   end
+
+  # favor monotonic clock if possible, and try to use clock_gettime in
+  # more recent Rubies since it generates less garbage
+  if defined?(Process::CLOCK_MONOTONIC)
+    def mono_now; Process.clock_gettime(Process::CLOCK_MONOTONIC); end
+  elsif defined?(Process::CLOCK_REALTIME)
+    def mono_now; Process.clock_gettime(Process::CLOCK_REALTIME); end
+  else
+    def mono_now; Time.now.to_f; end
+  end
 end
-- 
EW


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-02-27 22:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-27 22:45 [PATCH 0/2] fixes for pure-Ruby users Eric Wong
2015-02-27 22:45 ` [PATCH 1/2] pure: fix reentrancy of request_time Eric Wong
2015-02-27 22:45 ` [PATCH 2/2] pure: use monotonic clock if possible Eric Wong

Code repositories for project(s) associated with this public inbox

	https://yhbt.net/clogger.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).