clogger 0.9.0 → 1.0.0

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