From 8303d477a13a63e6b28666e04b0c62886feae48e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 16 Apr 2011 02:03:34 +0000 Subject: add support for $time_iso8601 format This appeared in nginx 0.9.6 --- README | 1 + ext/clogger_ext/clogger.c | 38 +++++++++++++++++++++++++++++++++++++- lib/clogger.rb | 3 ++- lib/clogger/pure.rb | 2 ++ test/test_clogger.rb | 36 ++++++++++++++++++++++++++++++++++++ 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 +#include #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 = [] -- cgit v1.2.3-24-ge0c7