about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-04-16 02:03:34 +0000
committerEric Wong <normalperson@yhbt.net>2011-04-16 02:06:36 +0000
commit8303d477a13a63e6b28666e04b0c62886feae48e (patch)
treefde9b917db48cad4dcd127cdf0fdce528348be53
parenta84b132f51bd011f3c3441c28d23ff9c1029a9f8 (diff)
downloadclogger-8303d477a13a63e6b28666e04b0c62886feae48e.tar.gz
This appeared in nginx 0.9.6
-rw-r--r--README1
-rw-r--r--ext/clogger_ext/clogger.c38
-rw-r--r--lib/clogger.rb3
-rw-r--r--lib/clogger/pure.rb2
-rw-r--r--test/test_clogger.rb36
5 files changed, 78 insertions, 2 deletions
diff --git a/README b/README
index f483c0f..598d976 100644
--- a/README
+++ b/README
@@ -73,6 +73,7 @@ that receives a "<<" method:
   (including response body iteration).  PRECISION defaults to 3
   (milliseconds) if not specified but may be specified anywhere from
   0(seconds) to 6(microseconds).
+* $time_iso8601 - time in ISO 8601 format
 * $time_local, $time_local{FORMAT} - current local time, FORMAT defaults to
   "%d/%b/%Y:%H:%M:%S %z" but accepts any strftime(3)-compatible format
 * $time_utc, $time_utc{FORMAT} - like $time_local, except with UTC
diff --git a/ext/clogger_ext/clogger.c b/ext/clogger_ext/clogger.c
index eb5347f..416ab30 100644
--- a/ext/clogger_ext/clogger.c
+++ b/ext/clogger_ext/clogger.c
@@ -17,6 +17,7 @@
 #  define _POSIX_C_SOURCE 200112L
 #endif
 #include <time.h>
+#include <stdlib.h>
 #include "ruby_1_9_compat.h"
 #include "broken_system_compat.h"
 #include "blocking_helpers.h"
@@ -89,7 +90,8 @@ enum clogger_special {
         CL_SP_response_length,
         CL_SP_ip,
         CL_SP_pid,
-        CL_SP_request_uri
+        CL_SP_request_uri,
+        CL_SP_time_iso8601,
 };
 
 struct clogger {
@@ -443,6 +445,37 @@ static void append_request_length(struct clogger *c)
         }
 }
 
+static long gmtoffset(struct tm *tm)
+{
+        time_t t = time(NULL);
+
+        tzset();
+        localtime_r(&t, tm);
+#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
+        return tm->tm_gmtoff / 60;
+#else
+        return -(tm->tm_isdst ? timezone - 3600 : timezone) / 60;
+#endif
+}
+
+static void append_time_iso8601(struct clogger *c)
+{
+        char buf[sizeof("1970-01-01T00:00:00+00:00")];
+        struct tm tm;
+        int nr;
+        long gmtoff = gmtoffset(&tm);
+
+        nr = snprintf(buf, sizeof(buf),
+                      "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
+                      tm.tm_year + 1900, tm.tm_mon + 1,
+                      tm.tm_mday, tm.tm_hour,
+                      tm.tm_min, tm.tm_sec,
+                      gmtoff < 0 ? '-' : '+',
+                      abs(gmtoff / 60), abs(gmtoff % 60));
+        assert(nr == (sizeof(buf) - 1) && "snprintf fail");
+        rb_str_buf_cat(c->log_buf, buf, sizeof(buf) - 1);
+}
+
 static void
 append_time(struct clogger *c, enum clogger_opcode op, VALUE fmt, VALUE buf)
 {
@@ -547,6 +580,9 @@ static void special_var(struct clogger *c, enum clogger_special var)
                 break;
         case CL_SP_request_uri:
                 append_request_uri(c);
+                break;
+        case CL_SP_time_iso8601:
+                append_time_iso8601(c);
         }
 }
 
diff --git a/lib/clogger.rb b/lib/clogger.rb
index 8058390..e368115 100644
--- a/lib/clogger.rb
+++ b/lib/clogger.rb
@@ -35,7 +35,8 @@ class Clogger
     :response_length => 4, # like body_bytes_sent, except "-" instead of "0"
     :ip => 5, # HTTP_X_FORWARDED_FOR || REMOTE_ADDR || -
     :pid => 6, # getpid()
-    :request_uri => 7
+    :request_uri => 7,
+    :time_iso8601 => 8,
   }
 
 private
diff --git a/lib/clogger/pure.rb b/lib/clogger/pure.rb
index 3737dd8..a56b982 100644
--- a/lib/clogger/pure.rb
+++ b/lib/clogger/pure.rb
@@ -135,6 +135,8 @@ private
       env['REMOTE_ADDR'] || '-'
     when :pid
       $$.to_s
+    when :time_iso8601
+      Time.now.iso8601
     else
       raise "EDOOFUS #{special_nr}"
     end
diff --git a/test/test_clogger.rb b/test/test_clogger.rb
index 06942c4..1a555ba 100644
--- a/test/test_clogger.rb
+++ b/test/test_clogger.rb
@@ -1,6 +1,7 @@
 # -*- encoding: binary -*-
 $stderr.sync = $stdout.sync = true
 require "test/unit"
+require "time"
 require "date"
 require "stringio"
 require "tempfile"
@@ -703,6 +704,41 @@ class TestClogger < Test::Unit::TestCase
     assert %r!\A\d+/\w+/\d{4}:\d\d:\d\d:\d\d \+0000\n\z! =~ s[0], s.inspect
   end
 
+  def test_time_iso8601
+    s = []
+    app = lambda { |env| [200, [], [] ] }
+    cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
+    status, headers, body = cl.call(@req)
+    t = Time.parse(s[0])
+    assert_equal t.iso8601, s[0].strip
+  end
+
+  def test_time_iso8601_pst8pdt
+    orig = ENV["TZ"]
+    ENV["TZ"] = "PST8PDT"
+    s = []
+    app = lambda { |env| [200, [], [] ] }
+    cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
+    status, headers, body = cl.call(@req)
+    t = Time.parse(s[0])
+    assert_equal t.iso8601, s[0].strip
+    ensure
+      ENV["TZ"] = orig
+  end
+
+  def test_time_iso8601_utc
+    orig = ENV["TZ"]
+    ENV["TZ"] = "UTC"
+    s = []
+    app = lambda { |env| [200, [], [] ] }
+    cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
+    status, headers, body = cl.call(@req)
+    t = Time.parse(s[0])
+    assert_equal t.iso8601, s[0].strip
+    ensure
+      ENV["TZ"] = orig
+  end
+
   def test_method_missing
     s = []
     body = []