clogger 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.9.0.GIT
4
+ DEF_VER=v1.0.0.GIT
5
5
 
6
6
  LF='
7
7
  '
data/README CHANGED
@@ -73,9 +73,10 @@ that receives a "<<" method:
73
73
  (including response body iteration). PRECISION defaults to 3
74
74
  (milliseconds) if not specified but may be specified anywhere from
75
75
  0(seconds) to 6(microseconds).
76
- * $time_local, $time_local{FORMAT} - current local time, FORMAT defaults to
77
- "%d/%b/%Y:%H:%M:%S %z" but accepts any strftime(3)-compatible format
78
- * $time_utc, $time_utc{FORMAT} - like $time_local, except with UTC
76
+ * $time_iso8601 - current local time in ISO 8601 format,
77
+ e.g. "1970-01-01T00:00:00+00:00"
78
+ * $time_local - current local time in Apache log format,
79
+ e.g. "01/Jan/1970:00:00:00 +0000"
79
80
  * $usec - current time in seconds.microseconds since the Epoch
80
81
  * $msec - current time in seconds.milliseconds since the Epoch
81
82
  * $body_bytes_sent - bytes in the response body (Apache: %B)
@@ -110,7 +111,7 @@ development. Patches should always be sent inline
110
111
 
111
112
  == CONTACT
112
113
 
113
- All feedback (bug reports, user/development dicussion, patches, pull
114
+ All feedback (bug reports, user/development discussion, patches, pull
114
115
  requests) go to the mailing list.
115
116
 
116
117
  * mailto:clogger@librelist.com
@@ -17,6 +17,7 @@
17
17
  # define _POSIX_C_SOURCE 200112L
18
18
  #endif
19
19
  #include <time.h>
20
+ #include <stdlib.h>
20
21
  #include "ruby_1_9_compat.h"
21
22
  #include "broken_system_compat.h"
22
23
  #include "blocking_helpers.h"
@@ -89,7 +90,10 @@ enum clogger_special {
89
90
  CL_SP_response_length,
90
91
  CL_SP_ip,
91
92
  CL_SP_pid,
92
- CL_SP_request_uri
93
+ CL_SP_request_uri,
94
+ CL_SP_time_iso8601,
95
+ CL_SP_time_local,
96
+ CL_SP_time_utc
93
97
  };
94
98
 
95
99
  struct clogger {
@@ -443,6 +447,75 @@ static void append_request_length(struct clogger *c)
443
447
  }
444
448
  }
445
449
 
450
+ static long local_gmtoffset(struct tm *tm)
451
+ {
452
+ time_t t = time(NULL);
453
+
454
+ tzset();
455
+ localtime_r(&t, tm);
456
+ #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
457
+ return tm->tm_gmtoff / 60;
458
+ #else
459
+ return -(tm->tm_isdst ? timezone - 3600 : timezone) / 60;
460
+ #endif
461
+ }
462
+
463
+ static void append_time_iso8601(struct clogger *c)
464
+ {
465
+ char buf[sizeof("1970-01-01T00:00:00+00:00")];
466
+ struct tm tm;
467
+ int nr;
468
+ long gmtoff = local_gmtoffset(&tm);
469
+
470
+ nr = snprintf(buf, sizeof(buf),
471
+ "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
472
+ tm.tm_year + 1900, tm.tm_mon + 1,
473
+ tm.tm_mday, tm.tm_hour,
474
+ tm.tm_min, tm.tm_sec,
475
+ gmtoff < 0 ? '-' : '+',
476
+ abs(gmtoff / 60), abs(gmtoff % 60));
477
+ assert(nr == (sizeof(buf) - 1) && "snprintf fail");
478
+ rb_str_buf_cat(c->log_buf, buf, sizeof(buf) - 1);
479
+ }
480
+
481
+ static const char months[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0"
482
+ "Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
483
+
484
+ static void append_time_local(struct clogger *c)
485
+ {
486
+ char buf[sizeof("01/Jan/1970:00:00:00 +0000")];
487
+ struct tm tm;
488
+ int nr;
489
+ long gmtoff = local_gmtoffset(&tm);
490
+
491
+ nr = snprintf(buf, sizeof(buf),
492
+ "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d",
493
+ tm.tm_mday, months + (tm.tm_mon * sizeof("Jan")),
494
+ tm.tm_year + 1900, tm.tm_hour,
495
+ tm.tm_min, tm.tm_sec,
496
+ gmtoff < 0 ? '-' : '+',
497
+ abs(gmtoff / 60), abs(gmtoff % 60));
498
+ assert(nr == (sizeof(buf) - 1) && "snprintf fail");
499
+ rb_str_buf_cat(c->log_buf, buf, sizeof(buf) - 1);
500
+ }
501
+
502
+ static void append_time_utc(struct clogger *c)
503
+ {
504
+ char buf[sizeof("01/Jan/1970:00:00:00 +0000")];
505
+ struct tm tm;
506
+ int nr;
507
+ time_t t = time(NULL);
508
+
509
+ gmtime_r(&t, &tm);
510
+ nr = snprintf(buf, sizeof(buf),
511
+ "%02d/%s/%d:%02d:%02d:%02d +0000",
512
+ tm.tm_mday, months + (tm.tm_mon * sizeof("Jan")),
513
+ tm.tm_year + 1900, tm.tm_hour,
514
+ tm.tm_min, tm.tm_sec);
515
+ assert(nr == (sizeof(buf) - 1) && "snprintf fail");
516
+ rb_str_buf_cat(c->log_buf, buf, sizeof(buf) - 1);
517
+ }
518
+
446
519
  static void
447
520
  append_time(struct clogger *c, enum clogger_opcode op, VALUE fmt, VALUE buf)
448
521
  {
@@ -547,6 +620,15 @@ static void special_var(struct clogger *c, enum clogger_special var)
547
620
  break;
548
621
  case CL_SP_request_uri:
549
622
  append_request_uri(c);
623
+ break;
624
+ case CL_SP_time_iso8601:
625
+ append_time_iso8601(c);
626
+ break;
627
+ case CL_SP_time_local:
628
+ append_time_local(c);
629
+ break;
630
+ case CL_SP_time_utc:
631
+ append_time_utc(c);
550
632
  }
551
633
  }
552
634
 
@@ -640,8 +722,8 @@ static void init_logger(struct clogger *c, VALUE path)
640
722
  *
641
723
  * Creates a new Clogger object that wraps +app+. +:logger+ may
642
724
  * be any object that responds to the "<<" method with a string argument.
643
- * If +:logger:+ is a string, it will be treated as a path to a
644
- * File that will be opened in append mode.
725
+ * Instead of +:logger+, +:path+ may be specified to be a :path of a File
726
+ * that will be opened in append mode.
645
727
  */
646
728
  static VALUE clogger_init(int argc, VALUE *argv, VALUE self)
647
729
  {
@@ -24,7 +24,6 @@ begin
24
24
  have_func('rb_str_set_len', 'ruby.h')
25
25
  have_func('rb_thread_blocking_region', 'ruby.h')
26
26
  have_func('rb_thread_io_blocking_region', 'ruby.h')
27
- dir_config('clogger_ext')
28
27
  create_makefile('clogger_ext')
29
28
  rescue Object => err
30
29
  warn "E: #{err.inspect}"
data/lib/clogger.rb CHANGED
@@ -19,8 +19,6 @@ class Clogger
19
19
  # support nginx variables that are less customizable than our own
20
20
  ALIASES = {
21
21
  '$request_time' => '$request_time{3}',
22
- '$time_local' => '$time_local{%d/%b/%Y:%H:%M:%S %z}',
23
- '$time_utc' => '$time_utc{%d/%b/%Y:%H:%M:%S %z}',
24
22
  '$msec' => '$time{3}',
25
23
  '$usec' => '$time{6}',
26
24
  '$http_content_length' => '$content_length',
@@ -35,7 +33,10 @@ class Clogger
35
33
  :response_length => 4, # like body_bytes_sent, except "-" instead of "0"
36
34
  :ip => 5, # HTTP_X_FORWARDED_FOR || REMOTE_ADDR || -
37
35
  :pid => 6, # getpid()
38
- :request_uri => 7
36
+ :request_uri => 7,
37
+ :time_iso8601 => 8,
38
+ :time_local => 9,
39
+ :time_utc => 10,
39
40
  }
40
41
 
41
42
  private
@@ -55,6 +56,7 @@ private
55
56
  \w*))?([^$]*)/x
56
57
 
57
58
  def compile_format(str, opt = {})
59
+ str = Clogger::Format.const_get(str) if Symbol === str
58
60
  longest_day = Time.at(26265600) # "Saturday, November 01, 1970 00:00:00"
59
61
  rv = []
60
62
  opt ||= {}
data/lib/clogger/pure.rb CHANGED
@@ -135,6 +135,20 @@ private
135
135
  env['REMOTE_ADDR'] || '-'
136
136
  when :pid
137
137
  $$.to_s
138
+ when :time_iso8601
139
+ Time.now.iso8601
140
+ when :time_local
141
+ t = Time.now
142
+ off = t.utc_offset
143
+ sign = off < 0 ? '-' : '+'
144
+ sprintf("%02d/%s/%d:%02d:%02d:%02d #{sign}%02d%02d",
145
+ t.mday, Time::RFC2822_MONTH_NAME[t.mon - 1],
146
+ t.year, t.hour, t.min, t.sec, *(off.abs / 60).divmod(60))
147
+ when :time_utc
148
+ t = Time.now.utc
149
+ sprintf("%02d/%s/%d:%02d:%02d:%02d +0000",
150
+ t.mday, Time::RFC2822_MONTH_NAME[t.mon - 1],
151
+ t.year, t.hour, t.min, t.sec)
138
152
  else
139
153
  raise "EDOOFUS #{special_nr}"
140
154
  end
data/test/test_clogger.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # -*- encoding: binary -*-
2
2
  $stderr.sync = $stdout.sync = true
3
3
  require "test/unit"
4
+ require "time"
4
5
  require "date"
5
6
  require "stringio"
6
7
  require "tempfile"
@@ -17,6 +18,8 @@ class TestClogger < Test::Unit::TestCase
17
18
  include Clogger::Format
18
19
 
19
20
  def setup
21
+ @tz = ENV["TZ"]
22
+ @nginx_fmt = "%d/%b/%Y:%H:%M:%S %z"
20
23
  @req = {
21
24
  "REQUEST_METHOD" => "GET",
22
25
  "HTTP_VERSION" => "HTTP/1.0",
@@ -29,6 +32,10 @@ class TestClogger < Test::Unit::TestCase
29
32
  }
30
33
  end
31
34
 
35
+ def teardown
36
+ ENV["TZ"] = @tz
37
+ end
38
+
32
39
  def test_init_basic
33
40
  Clogger.new(lambda { |env| [ 0, {}, [] ] })
34
41
  end
@@ -37,6 +44,11 @@ class TestClogger < Test::Unit::TestCase
37
44
  assert_raise(ArgumentError) { Clogger.new }
38
45
  end
39
46
 
47
+ def test_clogger_sym_format
48
+ app = lambda { |env| [ 0, {}, [] ] }
49
+ tmp = Clogger.new app, :format => :Rack_1_0, :logger => $stderr
50
+ end
51
+
40
52
  def test_init_stderr
41
53
  cl = Clogger.new(lambda { |env| [ 0, {}, [] ] }, :logger => $stderr)
42
54
  assert_kind_of(Integer, cl.fileno)
@@ -156,13 +168,12 @@ class TestClogger < Test::Unit::TestCase
156
168
  '$env{rack.url_scheme}' \
157
169
  "\n")
158
170
  }
159
- longest_day = Time.at(26265600).strftime('%d/%b/%Y:%H:%M:%S %z')
160
171
  expect = [
161
172
  [ Clogger::OP_REQUEST, "REMOTE_ADDR" ],
162
173
  [ Clogger::OP_LITERAL, " - " ],
163
174
  [ Clogger::OP_REQUEST, "REMOTE_USER" ],
164
175
  [ Clogger::OP_LITERAL, " [" ],
165
- [ Clogger::OP_TIME_LOCAL, '%d/%b/%Y:%H:%M:%S %z', longest_day ],
176
+ [ Clogger::OP_SPECIAL, Clogger::SPECIAL_VARS[:time_local] ],
166
177
  [ Clogger::OP_LITERAL, "] \"" ],
167
178
  [ Clogger::OP_SPECIAL, Clogger::SPECIAL_VARS[:request] ],
168
179
  [ Clogger::OP_LITERAL, "\" "],
@@ -698,6 +709,65 @@ class TestClogger < Test::Unit::TestCase
698
709
  assert %r!\A\d+/\w+/\d{4}:\d\d:\d\d:\d\d \+0000\n\z! =~ s[0], s.inspect
699
710
  end
700
711
 
712
+ def test_time_iso8601
713
+ s = []
714
+ app = lambda { |env| [200, [], [] ] }
715
+ cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
716
+ status, headers, body = cl.call(@req)
717
+ t = Time.parse(s[0])
718
+ assert_equal t.iso8601, s[0].strip
719
+ end
720
+
721
+ def test_time_iso8601_pst8pdt
722
+ ENV["TZ"] = "PST8PDT"
723
+ s = []
724
+ app = lambda { |env| [200, [], [] ] }
725
+ cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
726
+ status, headers, body = cl.call(@req)
727
+ t = Time.parse(s[0])
728
+ assert_equal t.iso8601, s[0].strip
729
+ end
730
+
731
+ def test_time_iso8601_utc
732
+ ENV["TZ"] = "UTC"
733
+ s = []
734
+ app = lambda { |env| [200, [], [] ] }
735
+ cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
736
+ status, headers, body = cl.call(@req)
737
+ t = Time.parse(s[0])
738
+ assert_equal t.iso8601, s[0].strip
739
+ end
740
+
741
+ def test_time_local
742
+ s = []
743
+ app = lambda { |env| [200, [], [] ] }
744
+ cl = Clogger.new(app, :logger => s, :format => "$time_local")
745
+ status, headers, body = cl.call(@req)
746
+ t = DateTime.strptime(s[0].strip, @nginx_fmt)
747
+ assert_equal t.strftime(@nginx_fmt), s[0].strip
748
+ end
749
+
750
+ def test_time_local_pst8pdt
751
+ orig = ENV["TZ"]
752
+ ENV["TZ"] = "PST8PDT"
753
+ s = []
754
+ app = lambda { |env| [200, [], [] ] }
755
+ cl = Clogger.new(app, :logger => s, :format => "$time_local")
756
+ status, headers, body = cl.call(@req)
757
+ t = DateTime.strptime(s[0].strip, @nginx_fmt)
758
+ assert_equal t.strftime(@nginx_fmt), s[0].strip
759
+ end
760
+
761
+ def test_time_local_utc
762
+ ENV["TZ"] = "UTC"
763
+ s = []
764
+ app = lambda { |env| [200, [], [] ] }
765
+ cl = Clogger.new(app, :logger => s, :format => "$time_local")
766
+ status, headers, body = cl.call(@req)
767
+ t = DateTime.strptime(s[0].strip, @nginx_fmt)
768
+ assert_equal t.strftime(@nginx_fmt), s[0].strip
769
+ end
770
+
701
771
  def test_method_missing
702
772
  s = []
703
773
  body = []
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clogger
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 9
9
9
  - 0
10
- version: 0.9.0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - cloggers
@@ -15,8 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-15 00:00:00 +00:00
19
- default_executable:
18
+ date: 2011-04-21 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: rack
@@ -94,7 +93,6 @@ files:
94
93
  - setup.rb
95
94
  - test/test_clogger.rb
96
95
  - test/test_clogger_to_path.rb
97
- has_rdoc: true
98
96
  homepage: http://clogger.rubyforge.org/
99
97
  licenses: []
100
98
 
@@ -128,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
126
  requirements: []
129
127
 
130
128
  rubyforge_project: clogger
131
- rubygems_version: 1.6.1
129
+ rubygems_version: 1.7.2
132
130
  signing_key:
133
131
  specification_version: 3
134
132
  summary: configurable request logging for Rack