clogger 0.6.0 → 0.7.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.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