clogger 0.6.0 → 0.7.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.6.0.GIT
4
+ DEF_VER=v0.7.0.GIT
5
5
 
6
6
  LF='
7
7
  '
data/GNUmakefile CHANGED
@@ -133,6 +133,7 @@ release: verify package $(release_notes) $(release_changes)
133
133
  gem push $(pkggem)
134
134
  rubyforge add_file \
135
135
  $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
136
+ $(RAKE) publish_news VERSION=$(VERSION)
136
137
  else
137
138
  gem install-gem: GIT-VERSION-FILE
138
139
  $(MAKE) $@ VERSION=$(GIT_VERSION)
data/README CHANGED
@@ -1,7 +1,5 @@
1
1
  = \Clogger - configurable request logging for Rack
2
2
 
3
- == DESCRIPTION
4
-
5
3
  \Clogger is Rack middleware for logging HTTP requests. The log format
6
4
  is customizable so you can specify exactly which fields to log.
7
5
 
@@ -26,7 +24,7 @@ is customizable so you can specify exactly which fields to log.
26
24
 
27
25
  * Pure Ruby version for non-MRI versions of Ruby (or via CLOGGER_PURE=1
28
26
  in the environment). The optional C extension is loaded by default
29
- and supported under MRI 1.8.7, 1.9.1, and 1.9.2.
27
+ and supported under MRI 1.8.7, 1.9.1, 1.9.2 and Rubinius.
30
28
 
31
29
  == SYNOPSIS
32
30
 
data/Rakefile CHANGED
@@ -5,11 +5,27 @@ rescue LoadError
5
5
  warn "rake-compiler not available, cross compiling disabled"
6
6
  end
7
7
 
8
- desc "read news article from STDIN and post to rubyforge"
8
+ cgit_url = "http://git.bogomips.org/cgit/clogger.git"
9
+ git_url = 'git://git.bogomips.org/clogger.git'
10
+
11
+ desc "post news article to rubyforge"
9
12
  task :publish_news do
10
13
  require 'rubyforge'
11
- IO.select([STDIN], nil, nil, 1) or abort "E: news must be read from stdin"
12
- msg = STDIN.readlines
14
+ spec = Gem::Specification.load('clogger.gemspec')
15
+ tmp = Tempfile.new('rf-news')
16
+ _, subject, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
17
+ tmp.puts subject
18
+ tmp.puts
19
+ tmp.puts spec.description.strip
20
+ tmp.puts ""
21
+ tmp.puts "* #{spec.homepage}"
22
+ tmp.puts "* #{spec.email}"
23
+ tmp.puts "* #{git_url}"
24
+ tmp.print "\nChanges:\n\n"
25
+ tmp.puts body
26
+ tmp.flush
27
+ system(ENV["VISUAL"], tmp.path) or abort "#{ENV["VISUAL"]} failed: #$?"
28
+ msg = File.readlines(tmp.path)
13
29
  subject = msg.shift
14
30
  blank = msg.shift
15
31
  blank == "\n" or abort "no newline after subject!"
@@ -21,9 +37,6 @@ task :publish_news do
21
37
  rf.post_news('clogger', subject, body)
22
38
  end
23
39
 
24
- cgit_url = "http://git.bogomips.org/cgit/clogger.git"
25
- git_url = 'git://git.bogomips.org/clogger.git'
26
-
27
40
  desc "post to RAA"
28
41
  task :raa_update do
29
42
  require 'rubygems'
@@ -0,0 +1,36 @@
1
+ /*
2
+ * this header includes functions to support broken systems
3
+ * without clock_gettime() or CLOCK_MONOTONIC
4
+ */
5
+
6
+ #ifndef HAVE_TYPE_CLOCKID_T
7
+ typedef int clockid_t;
8
+ #endif
9
+
10
+ #ifndef HAVE_CLOCK_GETTIME
11
+ # ifndef CLOCK_REALTIME
12
+ # define CLOCK_REALTIME 0 /* whatever */
13
+ # endif
14
+ static int fake_clock_gettime(clockid_t clk_id, struct timespec *res)
15
+ {
16
+ struct timeval tv;
17
+ int r = gettimeofday(&tv, NULL);
18
+
19
+ assert(0 == r && "gettimeofday() broke!?");
20
+ res->tv_sec = tv.tv_sec;
21
+ res->tv_nsec = tv.tv_usec * 1000;
22
+
23
+ return r;
24
+ }
25
+ # define clock_gettime fake_clock_gettime
26
+ #endif /* broken systems w/o clock_gettime() */
27
+
28
+ /*
29
+ * UGH
30
+ * CLOCK_MONOTONIC is not guaranteed to be a macro, either
31
+ */
32
+ #ifndef CLOCK_MONOTONIC
33
+ # if (!defined(_POSIX_MONOTONIC_CLOCK) || !defined(HAVE_CLOCK_MONOTONIC))
34
+ # define CLOCK_MONOTONIC CLOCK_REALTIME
35
+ # endif
36
+ #endif
@@ -13,9 +13,39 @@
13
13
  #ifdef HAVE_FCNTL_H
14
14
  # include <fcntl.h>
15
15
  #endif
16
- #define _POSIX_C_SOURCE 200112L
16
+ #ifndef _POSIX_C_SOURCE
17
+ # define _POSIX_C_SOURCE 200112L
18
+ #endif
17
19
  #include <time.h>
18
20
  #include "ruby_1_9_compat.h"
21
+ #include "broken_system_compat.h"
22
+
23
+ /*
24
+ * Availability of a monotonic clock needs to be detected at runtime
25
+ * since we could've been built on a different system than we're run
26
+ * under.
27
+ */
28
+ static clockid_t hopefully_CLOCK_MONOTONIC;
29
+
30
+ static void check_clock(void)
31
+ {
32
+ struct timespec now;
33
+
34
+ hopefully_CLOCK_MONOTONIC = CLOCK_MONOTONIC;
35
+
36
+ /* we can't check this reliably at compile time */
37
+ if (clock_gettime(CLOCK_MONOTONIC, &now) == 0)
38
+ return;
39
+
40
+ if (clock_gettime(CLOCK_REALTIME, &now) == 0) {
41
+ hopefully_CLOCK_MONOTONIC = CLOCK_REALTIME;
42
+ rb_warn("CLOCK_MONOTONIC not available, "
43
+ "falling back to CLOCK_REALTIME");
44
+ }
45
+ rb_warn("clock_gettime() totally broken, " \
46
+ "falling back to pure Ruby Clogger");
47
+ rb_raise(rb_eLoadError, "clock_gettime() broken");
48
+ }
19
49
 
20
50
  static void clock_diff(struct timespec *a, const struct timespec *b)
21
51
  {
@@ -94,8 +124,8 @@ static ID sq_brace_id;
94
124
  static ID new_id;
95
125
  static ID to_path_id;
96
126
  static ID to_io_id;
127
+ static ID respond_to_id;
97
128
  static VALUE cClogger;
98
- static VALUE cToPath;
99
129
  static VALUE mFormat;
100
130
  static VALUE cHeaderHash;
101
131
 
@@ -205,11 +235,6 @@ static struct clogger *clogger_get(VALUE self)
205
235
  return c;
206
236
  }
207
237
 
208
- static VALUE obj_fileno(VALUE obj)
209
- {
210
- return rb_funcall(obj, rb_intern("fileno"), 0);
211
- }
212
-
213
238
  /* only for writing to regular files, not stupid crap like NFS */
214
239
  static void write_full(int fd, const void *buf, size_t count)
215
240
  {
@@ -350,11 +375,8 @@ static void append_ts(struct clogger *c, const VALUE *op, struct timespec *ts)
350
375
  static void append_request_time_fmt(struct clogger *c, const VALUE *op)
351
376
  {
352
377
  struct timespec now;
353
- int r = clock_gettime(CLOCK_MONOTONIC, &now);
354
-
355
- if (unlikely(r != 0))
356
- rb_sys_fail("clock_gettime(CLOCK_MONONTONIC)");
357
378
 
379
+ clock_gettime(hopefully_CLOCK_MONOTONIC, &now);
358
380
  clock_diff(&now, &c->ts_start);
359
381
  append_ts(c, op, &now);
360
382
  }
@@ -420,10 +442,11 @@ static void append_request_length(struct clogger *c)
420
442
  }
421
443
  }
422
444
 
423
- static void append_time(struct clogger *c, enum clogger_opcode op, VALUE fmt)
445
+ static void
446
+ append_time(struct clogger *c, enum clogger_opcode op, VALUE fmt, VALUE buf)
424
447
  {
425
- /* you'd have to be a moron to use formats this big... */
426
- char buf[sizeof("Saturday, November 01, 1970, 00:00:00 PM +0000")];
448
+ char *buf_ptr = RSTRING_PTR(buf);
449
+ size_t buf_size = RSTRING_LEN(buf) + 1; /* "\0" */
427
450
  size_t nr;
428
451
  struct tm tmp;
429
452
  time_t t = time(NULL);
@@ -435,11 +458,9 @@ static void append_time(struct clogger *c, enum clogger_opcode op, VALUE fmt)
435
458
  else
436
459
  assert(0 && "unknown op");
437
460
 
438
- nr = strftime(buf, sizeof(buf), RSTRING_PTR(fmt), &tmp);
439
- if (nr == 0 || nr == sizeof(buf))
440
- rb_str_buf_append(c->log_buf, g_dash);
441
- else
442
- rb_str_buf_cat(c->log_buf, buf, nr);
461
+ nr = strftime(buf_ptr, buf_size, RSTRING_PTR(fmt), &tmp);
462
+ assert(nr < buf_size && "time format too small!");
463
+ rb_str_buf_cat(c->log_buf, buf_ptr, nr);
443
464
  }
444
465
 
445
466
  static void append_pid(struct clogger *c)
@@ -559,7 +580,7 @@ static VALUE cwrite(struct clogger *c)
559
580
  break;
560
581
  case CL_OP_TIME_LOCAL:
561
582
  case CL_OP_TIME_UTC:
562
- append_time(c, opcode, op[1]);
583
+ append_time(c, opcode, op[1], op[2]);
563
584
  break;
564
585
  case CL_OP_REQUEST_TIME:
565
586
  append_request_time_fmt(c, op);
@@ -728,7 +749,7 @@ static VALUE ccall(struct clogger *c, VALUE env)
728
749
  {
729
750
  VALUE rv;
730
751
 
731
- clock_gettime(CLOCK_MONOTONIC, &c->ts_start);
752
+ clock_gettime(hopefully_CLOCK_MONOTONIC, &c->ts_start);
732
753
  c->env = env;
733
754
  c->cookies = Qfalse;
734
755
  rv = rb_funcall(c->app, call_id, 1, env);
@@ -785,9 +806,6 @@ static VALUE clogger_call(VALUE self, VALUE env)
785
806
 
786
807
  rv = ccall(c, env);
787
808
  assert(!OBJ_FROZEN(rv) && "frozen response array");
788
-
789
- if (rb_respond_to(c->body, to_path_id))
790
- self = rb_funcall(cToPath, new_id, 1, self);
791
809
  rb_ary_store(rv, 2, self);
792
810
 
793
811
  return rv;
@@ -799,7 +817,24 @@ static VALUE clogger_call(VALUE self, VALUE env)
799
817
  return rv;
800
818
  }
801
819
 
802
- /* :nodoc */
820
+ static void duplicate_buffers(VALUE ops)
821
+ {
822
+ long i = RARRAY_LEN(ops);
823
+ VALUE *ary = RARRAY_PTR(ops);
824
+
825
+ for ( ; --i >= 0; ary++) {
826
+ VALUE *op = RARRAY_PTR(*ary);
827
+ enum clogger_opcode opcode = FIX2INT(op[0]);
828
+
829
+ if (opcode == CL_OP_TIME_LOCAL || opcode == CL_OP_TIME_UTC) {
830
+ Check_Type(op[2], T_STRING);
831
+ op[2] = rb_str_dup(op[2]);
832
+ rb_str_modify(op[2]); /* trigger copy-on-write */
833
+ }
834
+ }
835
+ }
836
+
837
+ /* :nodoc: */
803
838
  static VALUE clogger_init_copy(VALUE clone, VALUE orig)
804
839
  {
805
840
  struct clogger *a = clogger_get(orig);
@@ -807,6 +842,7 @@ static VALUE clogger_init_copy(VALUE clone, VALUE orig)
807
842
 
808
843
  memcpy(b, a, sizeof(struct clogger));
809
844
  init_buffers(b);
845
+ duplicate_buffers(b->fmt_ops);
810
846
 
811
847
  return clone;
812
848
  }
@@ -818,25 +854,38 @@ static VALUE clogger_init_copy(VALUE clone, VALUE orig)
818
854
 
819
855
  #define CONST_GLOBAL_STR(val) CONST_GLOBAL_STR2(val, #val)
820
856
 
821
- #ifdef RSTRUCT_PTR
822
- # define ToPath_clogger(tp) RSTRUCT_PTR(tp)[0]
823
- #else
824
- static ID clogger_id;
825
- # define ToPath_clogger(tp) rb_funcall(tp,clogger_id,0)
826
- #endif
857
+ /*
858
+ * call-seq:
859
+ * clogger.respond_to?(:to_path) => true or false
860
+ * clogger.respond_to?(:close) => true
861
+ *
862
+ * used to delegate +:to_path+ checks for Rack webservers that optimize
863
+ * static file serving
864
+ */
865
+ static VALUE respond_to(VALUE self, VALUE method)
866
+ {
867
+ struct clogger *c = clogger_get(self);
868
+ ID id = rb_to_id(method);
869
+
870
+ if (close_id == id)
871
+ return Qtrue;
872
+ return rb_respond_to(c->body, id);
873
+ }
827
874
 
875
+ /*
876
+ * call-seq:
877
+ * clogger.to_path
878
+ *
879
+ * used to proxy +:to_path+ method calls to the wrapped response body.
880
+ */
828
881
  static VALUE to_path(VALUE self)
829
882
  {
830
- VALUE my_clogger = ToPath_clogger(self);
831
- struct clogger *c = clogger_get(my_clogger);
883
+ struct clogger *c = clogger_get(self);
832
884
  VALUE path = rb_funcall(c->body, to_path_id, 0);
833
885
  struct stat sb;
834
886
  int rv;
835
887
  unsigned devfd;
836
- const char *cpath;
837
-
838
- Check_Type(path, T_STRING);
839
- cpath = RSTRING_PTR(path);
888
+ const char *cpath = StringValuePtr(path);
840
889
 
841
890
  /* try to avoid an extra path lookup */
842
891
  if (rb_respond_to(c->body, to_io_id))
@@ -863,6 +912,8 @@ void Init_clogger_ext(void)
863
912
  {
864
913
  VALUE tmp;
865
914
 
915
+ check_clock();
916
+
866
917
  ltlt_id = rb_intern("<<");
867
918
  call_id = rb_intern("call");
868
919
  each_id = rb_intern("each");
@@ -874,6 +925,7 @@ void Init_clogger_ext(void)
874
925
  new_id = rb_intern("new");
875
926
  to_path_id = rb_intern("to_path");
876
927
  to_io_id = rb_intern("to_io");
928
+ respond_to_id = rb_intern("respond_to?");
877
929
  cClogger = rb_define_class("Clogger", rb_cObject);
878
930
  mFormat = rb_define_module_under(cClogger, "Format");
879
931
  rb_define_alloc_func(cClogger, clogger_alloc);
@@ -885,6 +937,8 @@ void Init_clogger_ext(void)
885
937
  rb_define_method(cClogger, "fileno", clogger_fileno, 0);
886
938
  rb_define_method(cClogger, "wrap_body?", clogger_wrap_body, 0);
887
939
  rb_define_method(cClogger, "reentrant?", clogger_reentrant, 0);
940
+ rb_define_method(cClogger, "to_path", to_path, 0);
941
+ rb_define_method(cClogger, "respond_to?", respond_to, 1);
888
942
  CONST_GLOBAL_STR(REMOTE_ADDR);
889
943
  CONST_GLOBAL_STR(HTTP_X_FORWARDED_FOR);
890
944
  CONST_GLOBAL_STR(REQUEST_METHOD);
@@ -903,9 +957,4 @@ void Init_clogger_ext(void)
903
957
  tmp = rb_const_get(rb_cObject, rb_intern("Rack"));
904
958
  tmp = rb_const_get(tmp, rb_intern("Utils"));
905
959
  cHeaderHash = rb_const_get(tmp, rb_intern("HeaderHash"));
906
- cToPath = rb_const_get(cClogger, rb_intern("ToPath"));
907
- rb_define_method(cToPath, "to_path", to_path, 0);
908
- #ifndef RSTRUCT_PTR
909
- clogger_id = rb_intern("clogger");
910
- #endif
911
960
  }
@@ -13,10 +13,12 @@ begin
13
13
  have_macro('O_NONBLOCK', %w(unistd.h fcntl.h))
14
14
  end
15
15
 
16
- unless have_macro('CLOCK_MONOTONIC', 'time.h', '-D_POSIX_C_SOURCE=200112L')
17
- $CPPFLAGS += '-D_POSIX_SOURCE_200112L'
16
+ $CPPFLAGS += '-D_POSIX_C_SOURCE=200112L'
17
+ unless have_macro('CLOCK_MONOTONIC', 'time.h')
18
18
  have_func('CLOCK_MONOTONIC', 'time.h')
19
19
  end
20
+ have_type('clockid_t', 'time.h')
21
+ have_func('clock_gettime', 'time.h')
20
22
  have_func('localtime_r', 'time.h') or raise "localtime_r needed"
21
23
  have_func('gmtime_r', 'time.h') or raise "gmtime_r needed"
22
24
  have_func('rb_str_set_len', 'ruby.h')
@@ -11,14 +11,6 @@
11
11
  #ifndef RARRAY_LEN
12
12
  # define RARRAY_LEN(s) (RARRAY(s)->len)
13
13
  #endif
14
- #ifndef RUBINIUS
15
- # ifndef RSTRUCT_PTR
16
- # define RSTRUCT_PTR(s) (RSTRUCT(s)->ptr)
17
- # endif
18
- # ifndef RSTRUCT_LEN
19
- # define RSTRUCT_LEN(s) (RSTRUCT(s)->len)
20
- # endif
21
- #endif
22
14
 
23
15
  #ifndef HAVE_RB_STR_SET_LEN
24
16
  /* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
data/lib/clogger.rb CHANGED
@@ -4,8 +4,8 @@ require 'rack'
4
4
  # See the README for usage instructions
5
5
  class Clogger
6
6
 
7
- # the version of Clogger, currently 0.6.0
8
- VERSION = '0.6.0'
7
+ # the version of Clogger, currently 0.7.0
8
+ VERSION = '0.7.0'
9
9
 
10
10
  # :stopdoc:
11
11
  OP_LITERAL = 0
@@ -23,6 +23,7 @@ class Clogger
23
23
  ALIASES = {
24
24
  '$request_time' => '$request_time{3}',
25
25
  '$time_local' => '$time_local{%d/%b/%Y:%H:%M:%S %z}',
26
+ '$time_utc' => '$time_utc{%d/%b/%Y:%H:%M:%S %z}',
26
27
  '$msec' => '$time{3}',
27
28
  '$usec' => '$time{6}',
28
29
  '$http_content_length' => '$content_length',
@@ -40,15 +41,6 @@ class Clogger
40
41
  :request_uri => 7
41
42
  }
42
43
 
43
- # proxy class to avoid clobbering the +to_path+ optimization when
44
- # using static files
45
- class ToPath < Struct.new(:clogger)
46
- def each(&block); clogger.each(&block); end
47
- def close; clogger.close; end
48
-
49
- # to_path is defined in Clogger::Pure or the C extension
50
- end
51
-
52
44
  private
53
45
 
54
46
  CGI_ENV = Regexp.new('\A\$(' <<
@@ -66,6 +58,7 @@ private
66
58
  \w*))?([^$]*)/x
67
59
 
68
60
  def compile_format(str, opt = {})
61
+ longest_day = Time.at(26265600) # "Saturday, November 01, 1970 00:00:00"
69
62
  rv = []
70
63
  opt ||= {}
71
64
  str.scan(SCAN).each do |pre,tok,post|
@@ -92,9 +85,11 @@ private
92
85
  when /\A\$sent_http_(\w+)\z/
93
86
  rv << [ OP_RESPONSE, $1.downcase.tr('_','-') ]
94
87
  when /\A\$time_local\{([^\}]+)\}\z/
95
- rv << [ OP_TIME_LOCAL, $1 ]
88
+ fmt = $1
89
+ rv << [ OP_TIME_LOCAL, fmt, longest_day.strftime(fmt) ]
96
90
  when /\A\$time_utc\{([^\}]+)\}\z/
97
- rv << [ OP_TIME_UTC, $1 ]
91
+ fmt = $1
92
+ rv << [ OP_TIME_UTC, fmt, longest_day.strftime(fmt) ]
98
93
  when /\A\$time\{(\d+)\}\z/
99
94
  rv << [ OP_TIME, *usec_conv_pair(tok, $1.to_i) ]
100
95
  when /\A\$request_time\{(\d+)\}\z/
data/lib/clogger/pure.rb CHANGED
@@ -43,7 +43,6 @@ class Clogger
43
43
  wbody.status = status
44
44
  wbody.headers = headers
45
45
  wbody.body = body
46
- wbody = Clogger::ToPath.new(wbody) if body.respond_to?(:to_path)
47
46
  return [ status, headers, wbody ]
48
47
  end
49
48
  log(env, status, headers)
@@ -77,6 +76,19 @@ class Clogger
77
76
  @logger.respond_to?(:fileno) ? @logger.fileno : nil
78
77
  end
79
78
 
79
+ def respond_to?(m)
80
+ :close == m.to_sym || @body.respond_to?(m)
81
+ end
82
+
83
+ def to_path
84
+ rv = @body.to_path
85
+ # try to avoid unnecessary path lookups with to_io.stat instead of
86
+ # File.size
87
+ @body_bytes_sent =
88
+ @body.respond_to?(:to_io) ? @body.to_io.stat.size : File.size(rv)
89
+ rv
90
+ end
91
+
80
92
  private
81
93
 
82
94
  def byte_xs(s)
@@ -151,17 +163,4 @@ private
151
163
  end
152
164
  }.join('')
153
165
  end
154
-
155
- class ToPath
156
- def to_path
157
- rv = (body = clogger.body).to_path
158
-
159
- # try to avoid unnecessary path lookups with to_io.stat instead of
160
- # File.stat
161
- clogger.body_bytes_sent =
162
- (body.respond_to?(:to_io) ? body.to_io.stat : File.stat(rv)).size
163
- rv
164
- end
165
- end
166
-
167
166
  end
data/test/test_clogger.rb CHANGED
@@ -156,12 +156,13 @@ class TestClogger < Test::Unit::TestCase
156
156
  '$env{rack.url_scheme}' \
157
157
  "\n")
158
158
  }
159
+ longest_day = Time.at(26265600).strftime('%d/%b/%Y:%H:%M:%S %z')
159
160
  expect = [
160
161
  [ Clogger::OP_REQUEST, "REMOTE_ADDR" ],
161
162
  [ Clogger::OP_LITERAL, " - " ],
162
163
  [ Clogger::OP_REQUEST, "REMOTE_USER" ],
163
164
  [ Clogger::OP_LITERAL, " [" ],
164
- [ Clogger::OP_TIME_LOCAL, '%d/%b/%Y:%H:%M:%S %z' ],
165
+ [ Clogger::OP_TIME_LOCAL, '%d/%b/%Y:%H:%M:%S %z', longest_day ],
165
166
  [ Clogger::OP_LITERAL, "] \"" ],
166
167
  [ Clogger::OP_SPECIAL, Clogger::SPECIAL_VARS[:request] ],
167
168
  [ Clogger::OP_LITERAL, "\" "],
@@ -677,4 +678,23 @@ class TestClogger < Test::Unit::TestCase
677
678
  assert s[-1].to_f >= 0.100
678
679
  assert s[-1].to_f <= 0.110
679
680
  end
681
+
682
+ def test_insanely_long_time_format
683
+ s = []
684
+ app = lambda { |env| [200, [], [] ] }
685
+ fmt = '%Y' * 100
686
+ expect = Time.now.utc.strftime(fmt) << "\n"
687
+ assert_equal 100 * 4 + 1, expect.size
688
+ cl = Clogger.new(app, :logger => s, :format => "$time_utc{#{fmt}}")
689
+ status, headers, body = cl.call(@req)
690
+ assert_equal expect, s[0]
691
+ end
692
+
693
+ def test_time_utc
694
+ s = []
695
+ app = lambda { |env| [200, [], [] ] }
696
+ cl = Clogger.new(app, :logger => s, :format => "$time_utc")
697
+ status, headers, body = cl.call(@req)
698
+ assert %r!\A\d+/\w+/\d{4}:\d\d:\d\d:\d\d \+0000\n\z! =~ s[0], s.inspect
699
+ end
680
700
  end
@@ -31,6 +31,14 @@ class TestCloggerToPath < Test::Unit::TestCase
31
31
  }
32
32
  end
33
33
 
34
+ def check_body(body)
35
+ assert body.respond_to?(:to_path)
36
+ assert body.respond_to?("to_path")
37
+
38
+ assert ! body.respond_to?(:to_Path)
39
+ assert ! body.respond_to?("to_Path")
40
+ end
41
+
34
42
  def test_wraps_to_path
35
43
  logger = StringIO.new
36
44
  tmp = Tempfile.new('')
@@ -49,7 +57,8 @@ class TestCloggerToPath < Test::Unit::TestCase
49
57
  end.to_app
50
58
 
51
59
  status, headers, body = app.call(@req)
52
- assert_instance_of(Clogger::ToPath, body)
60
+ assert_instance_of(Clogger, body)
61
+ check_body(body)
53
62
  assert logger.string.empty?
54
63
  assert_equal tmp.path, body.to_path
55
64
  body.close
@@ -75,7 +84,8 @@ class TestCloggerToPath < Test::Unit::TestCase
75
84
  end.to_app
76
85
 
77
86
  status, headers, body = app.call(@req)
78
- assert_instance_of(Clogger::ToPath, body)
87
+ assert_instance_of(Clogger, body)
88
+ check_body(body)
79
89
  assert logger.string.empty?
80
90
  assert_equal "/dev/fd/#{tmp.fileno}", body.to_path
81
91
  body.close
@@ -107,7 +117,9 @@ class TestCloggerToPath < Test::Unit::TestCase
107
117
  end.to_app
108
118
 
109
119
  status, headers, body = app.call(@req)
110
- assert_instance_of(Clogger::ToPath, body)
120
+ assert_instance_of(Clogger, body)
121
+ check_body(body)
122
+
111
123
  body.to_path
112
124
  assert_kind_of IO, tmp.instance_variable_get(:@to_io_called)
113
125
  assert logger.string.empty?
@@ -132,6 +144,8 @@ class TestCloggerToPath < Test::Unit::TestCase
132
144
  end.to_app
133
145
  status, headers, body = app.call(@req)
134
146
  assert_instance_of(Clogger, body)
147
+ assert ! body.respond_to?(:to_path)
148
+ assert ! body.respond_to?("to_path")
135
149
  assert logger.string.empty?
136
150
  body.close
137
151
  assert ! logger.string.empty?
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: 7
4
+ hash: 3
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 6
8
+ - 7
9
9
  - 0
10
- version: 0.6.0
10
+ version: 0.7.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - cloggers
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-25 00:00:00 +00:00
18
+ date: 2011-01-15 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -48,7 +48,9 @@ dependencies:
48
48
  version: "1.0"
49
49
  type: :development
50
50
  version_requirements: *id002
51
- description: == DESCRIPTION
51
+ description: |-
52
+ \Clogger is Rack middleware for logging HTTP requests. The log format
53
+ is customizable so you can specify exactly which fields to log.
52
54
  email: clogger@librelist.com
53
55
  executables: []
54
56
 
@@ -80,6 +82,7 @@ files:
80
82
  - README
81
83
  - Rakefile
82
84
  - clogger.gemspec
85
+ - ext/clogger_ext/broken_system_compat.h
83
86
  - ext/clogger_ext/clogger.c
84
87
  - ext/clogger_ext/extconf.rb
85
88
  - ext/clogger_ext/ruby_1_9_compat.h