clogger 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document CHANGED
@@ -4,3 +4,4 @@ ChangeLog
4
4
  lib
5
5
  ext/clogger_ext/clogger.c
6
6
  LICENSE
7
+ LATEST
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ Makefile
15
15
  /ChangeLog
16
16
  /NEWS
17
17
  /GIT-VERSION-FILE
18
+ /LATEST
data/.wrongdoc.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ rdoc_url: http://clogger.rubyforge.org/
3
+ cgit_url: http://git.bogomips.org/cgit/clogger.git
4
+ git_url: git://git.bogomips.org/clogger.git
5
+ changelog_since: 0.4.0
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.5.0.GIT
4
+ DEF_VER=v0.6.0.GIT
5
5
 
6
6
  LF='
7
7
  '
data/GNUmakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  all:: test
2
2
  RUBY = ruby
3
3
  RAKE = rake
4
- GIT_URL = git://git.bogomips.org/clogger.git
4
+ RSYNC = rsync
5
5
 
6
6
  GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
7
7
  @./GIT-VERSION-GEN
@@ -26,24 +26,24 @@ test_unit := $(wildcard test/test_*.rb)
26
26
  test-unit: $(test_unit)
27
27
 
28
28
  ifeq ($(CLOGGER_PURE),)
29
- $(test_unit): export RUBYLIB := ext/clogger_ext:lib
29
+ $(test_unit): mylib := ext/clogger_ext:lib
30
30
  $(test_unit): ext/clogger_ext/clogger.$(DLEXT)
31
31
  else
32
- $(test_unit): export RUBYLIB := lib
32
+ $(test_unit): mylib := lib
33
33
  endif
34
34
 
35
35
  $(test_unit):
36
- $(RUBY) $@
36
+ $(RUBY) -I $(mylib) $@
37
37
 
38
38
  test-ext:
39
- CLOGGER_PURE=0 $(MAKE) test-unit
39
+ CLOGGER_PURE= $(MAKE) test-unit
40
40
 
41
41
  test-pure:
42
42
  CLOGGER_PURE=1 $(MAKE) test-unit
43
43
 
44
44
  test: test-ext test-pure
45
45
 
46
- pkg_extra := GIT-VERSION-FILE NEWS ChangeLog
46
+ pkg_extra := GIT-VERSION-FILE NEWS ChangeLog LATEST
47
47
  manifest: $(pkg_extra)
48
48
  $(RM) .manifest
49
49
  $(MAKE) .manifest
@@ -55,44 +55,25 @@ manifest: $(pkg_extra)
55
55
  cmp $@+ $@ || mv $@+ $@
56
56
  $(RM) $@+
57
57
 
58
- NEWS: GIT-VERSION-FILE .manifest
59
- $(RAKE) -s news_rdoc > $@+
60
- mv $@+ $@
61
-
62
- SINCE = 0.4.0
63
- ChangeLog: log_range = $(shell test -n "$(SINCE)" && echo v$(SINCE)..)
64
- ChangeLog: GIT-VERSION-FILE
65
- @echo "ChangeLog from $(GIT_URL) ($(SINCE)..$(GIT_VERSION))" > $@+
66
- @echo >> $@+
67
- git log $(log_range) | sed -e 's/^/ /' >> $@+
68
- mv $@+ $@
58
+ ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
59
+ wrongdoc prepare
69
60
 
70
- news_atom := http://clogger.rubyforge.org/NEWS.atom.xml
71
- cgit_atom := http://git.bogomips.org/cgit/clogger.git/atom/?h=master
72
- atom = <link rel="alternate" title="Atom feed" href="$(1)" \
73
- type="application/atom+xml"/>
74
-
75
- doc: .document NEWS ChangeLog
76
- rdoc -a -t "$(shell sed -ne '1s/^= //p' README)"
61
+ doc: .document .wrongdoc.yml
62
+ find lib ext -type f -name '*.rbc' -exec rm -f '{}' ';'
63
+ $(RM) -r doc
64
+ wrongdoc all
77
65
  install -m644 COPYING doc/COPYING
78
- install -m644 $(shell grep '^[A-Z]' .document) doc/
79
- $(RUBY) -i -p -e \
80
- '$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
81
- doc/ChangeLog.html
82
- $(RUBY) -i -p -e \
83
- '$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
84
- doc/NEWS.html doc/README.html
85
- $(RAKE) -s news_atom > doc/NEWS.atom.xml
86
- cd doc && ln README.html tmp && mv tmp index.html
66
+ install -m644 $(shell grep '^[A-Z]' .document) doc/
87
67
 
88
68
  # publishes docs to http://clogger.rubyforge.org/
89
69
  # this preserves timestamps as best as possible to help HTTP caches out
90
70
  # git set-file-times is here: http://git-scm.org/gitwiki/ExampleScripts
91
71
  publish_doc:
92
- git set-file-times
93
- $(RM) -r doc
72
+ -git set-file-times
94
73
  $(MAKE) doc
95
- rsync -av doc/ rubyforge.org:/var/www/gforge-projects/clogger/
74
+ -find doc/images -type f | \
75
+ TZ=UTC xargs touch -d '1970-01-01 00:00:03' doc/rdoc.css
76
+ $(RSYNC) -av doc/ rubyforge.org:/var/www/gforge-projects/clogger/
96
77
  git ls-files | xargs touch
97
78
 
98
79
  ifneq ($(VERSION),)
@@ -106,10 +87,10 @@ release_changes := release_changes-$(VERSION)
106
87
  release-notes: $(release_notes)
107
88
  release-changes: $(release_changes)
108
89
  $(release_changes):
109
- $(RAKE) -s release_changes > $@+
90
+ wrongdoc release_changes > $@+
110
91
  $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
111
92
  $(release_notes):
112
- GIT_URL=$(GIT_URL) $(RAKE) -s release_notes > $@+
93
+ wrongdoc release_notes > $@+
113
94
  $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
114
95
 
115
96
  # ensures we're actually on the tagged $(VERSION), only used for release
@@ -140,8 +121,8 @@ $(pkgtgz): manifest fix-perms
140
121
  @test -n "$(distdir)"
141
122
  $(RM) -r $(distdir)
142
123
  mkdir -p $(distdir)
143
- tar c `cat .manifest` | (cd $(distdir) && tar x)
144
- cd pkg && tar c $(basename $(@F)) | gzip -9 > $(@F)+
124
+ tar cf - `cat .manifest` | (cd $(distdir) && tar xf -)
125
+ cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
145
126
  mv $@+ $@
146
127
 
147
128
  package: $(pkgtgz) $(pkggem)
data/README CHANGED
@@ -10,7 +10,7 @@ is customizable so you can specify exactly which fields to log.
10
10
  * highly customizable with easy-to-read nginx-like log format variables.
11
11
 
12
12
  * pre-defines Apache Common Log Format, Apache Combined Log Format and
13
- Rack::CommonLogger (as distributed by Rack 1.0) formats.
13
+ Rack::CommonLogger (as distributed by Rack 1.0 and 1.1) formats.
14
14
  See Clogger::Format for the predefined formats.
15
15
 
16
16
  * Untrusted values are escaped (all HTTP headers, request URI components)
@@ -36,7 +36,7 @@ is customizable so you can specify exactly which fields to log.
36
36
  require "clogger"
37
37
  use Clogger,
38
38
  :format => Clogger::Format::Combined,
39
- :logger => ::File.open("/path/to/log", "ab"),
39
+ :path => "/path/to/log",
40
40
  :reentrant => true
41
41
  run YourApplication.new
42
42
 
@@ -45,9 +45,15 @@ somewhere inside the "Rails::Initializer.run do |config|" block:
45
45
 
46
46
  config.middleware.use 'Clogger',
47
47
  :format => Clogger::Format::Combined,
48
- :logger => ::File.open("/path/to/log", "ab"),
48
+ :path => "/path/to/log",
49
49
  :reentrant => false
50
50
 
51
+ Instead of specifying a :path, you may also specify a :logger object
52
+ that receives a "<<" method:
53
+
54
+ use Clogger, :logger=> $stdout, :reentrant => true
55
+ run YourApplication.new
56
+
51
57
  == VARIABLES
52
58
 
53
59
  * $http_* - HTTP request headers (e.g. $http_user_agent)
data/Rakefile CHANGED
@@ -21,101 +21,8 @@ task :publish_news do
21
21
  rf.post_news('clogger', subject, body)
22
22
  end
23
23
 
24
- def tags
25
- timefmt = '%Y-%m-%dT%H:%M:%SZ'
26
- @tags ||= `git tag -l`.split(/\n/).map do |tag|
27
- next if tag == "v0.0.0"
28
- if %r{\Av[\d\.]+\z} =~ tag
29
- header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
30
- header = header.split(/\n/)
31
- tagger = header.grep(/\Atagger /).first
32
- body ||= "initial"
33
- {
34
- :time => Time.at(tagger.split(/ /)[-2].to_i).utc.strftime(timefmt),
35
- :tagger_name => %r{^tagger ([^<]+)}.match(tagger)[1],
36
- :tagger_email => %r{<([^>]+)>}.match(tagger)[1],
37
- :id => `git rev-parse refs/tags/#{tag}`.chomp!,
38
- :tag => tag,
39
- :subject => subject,
40
- :body => body,
41
- }
42
- end
43
- end.compact.sort { |a,b| b[:time] <=> a[:time] }
44
- end
45
-
46
24
  cgit_url = "http://git.bogomips.org/cgit/clogger.git"
47
- git_url = ENV['GIT_URL'] || 'git://git.bogomips.org/clogger.git'
48
-
49
- desc 'prints news as an Atom feed'
50
- task :news_atom do
51
- require 'nokogiri'
52
- new_tags = tags[0,10]
53
- puts(Nokogiri::XML::Builder.new do
54
- feed :xmlns => "http://www.w3.org/2005/Atom" do
55
- id! "http://clogger.rubyforge.org/NEWS.atom.xml"
56
- title "Clogger news"
57
- subtitle "configurable request logging for Rack"
58
- link! :rel => 'alternate', :type => 'text/html',
59
- :href => 'http://clogger.rubyforge.org/NEWS.html'
60
- updated new_tags.first[:time]
61
- new_tags.each do |tag|
62
- entry do
63
- title tag[:subject]
64
- updated tag[:time]
65
- published tag[:time]
66
- author {
67
- name tag[:tagger_name]
68
- email tag[:tagger_email]
69
- }
70
- url = "#{cgit_url}/tag/?id=#{tag[:tag]}"
71
- link! :rel => "alternate", :type => "text/html", :href =>url
72
- id! url
73
- content(:type => 'text') { tag[:body] }
74
- end
75
- end
76
- end
77
- end.to_xml)
78
- end
79
-
80
- desc 'prints RDoc-formatted news'
81
- task :news_rdoc do
82
- tags.each do |tag|
83
- time = tag[:time].tr!('T', ' ').gsub!(/:\d\dZ/, ' UTC')
84
- puts "=== #{tag[:tag].sub(/^v/, '')} / #{time}"
85
- puts ""
86
-
87
- body = tag[:body]
88
- puts tag[:body].gsub(/^/sm, " ").gsub(/[ \t]+$/sm, "")
89
- puts ""
90
- end
91
- end
92
-
93
- desc "print release changelog for Rubyforge"
94
- task :release_changes do
95
- version = ENV['VERSION'] or abort "VERSION= needed"
96
- version = "v#{version}"
97
- vtags = tags.map { |tag| tag[:tag] =~ /\Av/ and tag[:tag] }.sort
98
- prev = vtags[vtags.index(version) - 1]
99
- system('git', 'diff', '--stat', prev, version) or abort $?
100
- puts ""
101
- system('git', 'log', "#{prev}..#{version}") or abort $?
102
- end
103
-
104
- desc "print release notes for Rubyforge"
105
- task :release_notes do
106
- require 'rubygems'
107
-
108
- spec = Gem::Specification.load('clogger.gemspec')
109
- puts spec.description.strip
110
- puts ""
111
- puts "* #{spec.homepage}"
112
- puts "* #{spec.email}"
113
- puts "* #{git_url}"
114
-
115
- _, _, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
116
- print "\nChanges:\n\n"
117
- puts body
118
- end
25
+ git_url = 'git://git.bogomips.org/clogger.git'
119
26
 
120
27
  desc "post to RAA"
121
28
  task :raa_update do
data/clogger.gemspec CHANGED
@@ -1,44 +1,28 @@
1
1
  ENV["VERSION"] or abort "VERSION= must be specified"
2
2
  manifest = File.readlines('.manifest').map! { |x| x.chomp! }
3
+ require 'wrongdoc'
4
+ extend Wrongdoc::Gemspec
5
+ name, summary, title = readme_metadata
3
6
 
4
7
  Gem::Specification.new do |s|
5
8
  s.name = %q{clogger}
6
- s.version = ENV["VERSION"]
7
-
8
- if s.respond_to? :required_rubygems_version=
9
- s.required_rubygems_version = Gem::Requirement.new(">= 0")
10
- end
11
- s.homepage = 'http://clogger.rubyforge.org/'
9
+ s.version = ENV["VERSION"].dup
10
+ s.homepage = Wrongdoc.config[:rdoc_url]
12
11
  s.authors = ["cloggers"]
13
12
  s.date = Time.now.utc.strftime('%Y-%m-%d')
14
- s.description = %q{
15
- Clogger is Rack middleware for logging HTTP requests. The log format
16
- is customizable so you can specify exactly which fields to log.
17
- }.strip
13
+ s.description = readme_description
18
14
  s.email = %q{clogger@librelist.com}
19
-
20
- s.extra_rdoc_files = File.readlines('.document').map! do |x|
21
- x.chomp!
22
- if File.directory?(x)
23
- manifest.grep(%r{\A#{x}/})
24
- elsif File.file?(x)
25
- x
26
- else
27
- nil
28
- end
29
- end.flatten.compact
30
-
15
+ s.extra_rdoc_files = extra_rdoc_files(manifest)
31
16
  s.files = manifest
32
- s.rdoc_options = [ "-Na",
33
- "-t", "Clogger - configurable request logging for Rack"
34
- ]
17
+ s.rdoc_options = rdoc_options
35
18
  s.require_paths = %w(lib ext)
36
19
  s.rubyforge_project = %q{clogger}
37
- s.summary = %q{configurable request logging for Rack}
20
+ s.summary = summary
38
21
  s.test_files = %w(test/test_clogger.rb test/test_clogger_to_path.rb)
39
22
 
40
23
  # HeaderHash wasn't case-insensitive in old versions
41
24
  s.add_dependency(%q<rack>, ["> 0.9"])
25
+ s.add_development_dependency(%q<wrongdoc>, "~> 1.0")
42
26
  s.extensions = %w(ext/clogger_ext/extconf.rb)
43
27
 
44
28
  # s.license = "LGPLv2.1+" # disabled for compatibility with older RubyGems
@@ -1,4 +1,3 @@
1
- #define _BSD_SOURCE
2
1
  #include <ruby.h>
3
2
  #ifdef HAVE_RUBY_IO_H
4
3
  # include <ruby/io.h>
@@ -10,25 +9,23 @@
10
9
  #include <sys/types.h>
11
10
  #include <sys/stat.h>
12
11
  #include <sys/time.h>
13
- #include <time.h>
14
12
  #include <errno.h>
15
13
  #ifdef HAVE_FCNTL_H
16
14
  # include <fcntl.h>
17
15
  #endif
16
+ #define _POSIX_C_SOURCE 200112L
17
+ #include <time.h>
18
18
  #include "ruby_1_9_compat.h"
19
19
 
20
- /* in case _BSD_SOURCE doesn't give us this macro */
21
- #ifndef timersub
22
- # define timersub(a, b, result) \
23
- do { \
24
- (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
25
- (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
26
- if ((result)->tv_usec < 0) { \
27
- --(result)->tv_sec; \
28
- (result)->tv_usec += 1000000; \
29
- } \
30
- } while (0)
31
- #endif
20
+ static void clock_diff(struct timespec *a, const struct timespec *b)
21
+ {
22
+ a->tv_sec -= b->tv_sec;
23
+ a->tv_nsec -= b->tv_nsec;
24
+ if (a->tv_nsec < 0) {
25
+ --a->tv_sec;
26
+ a->tv_nsec += 1000000000;
27
+ }
28
+ }
32
29
 
33
30
  /* give GCC hints for better branch prediction
34
31
  * (we layout branches so that ASCII characters are handled faster) */
@@ -78,7 +75,7 @@ struct clogger {
78
75
  VALUE body;
79
76
 
80
77
  off_t body_bytes_sent;
81
- struct timeval tv_start;
78
+ struct timespec ts_start;
82
79
 
83
80
  int fd;
84
81
  int wrap_body;
@@ -213,11 +210,6 @@ static VALUE obj_fileno(VALUE obj)
213
210
  return rb_funcall(obj, rb_intern("fileno"), 0);
214
211
  }
215
212
 
216
- static VALUE obj_enable_sync(VALUE obj)
217
- {
218
- return rb_funcall(obj, rb_intern("sync="), 1, Qtrue);
219
- }
220
-
221
213
  /* only for writing to regular files, not stupid crap like NFS */
222
214
  static void write_full(int fd, const void *buf, size_t count)
223
215
  {
@@ -341,34 +333,40 @@ static void append_body_bytes_sent(struct clogger *c)
341
333
  rb_str_buf_cat(c->log_buf, buf, nr);
342
334
  }
343
335
 
344
- static void append_tv(struct clogger *c, const VALUE *op, struct timeval *tv)
336
+ static void append_ts(struct clogger *c, const VALUE *op, struct timespec *ts)
345
337
  {
346
- char buf[sizeof(".000000") + ((sizeof(tv->tv_sec) * 8) / 3)];
338
+ char buf[sizeof(".000000") + ((sizeof(ts->tv_sec) * 8) / 3)];
347
339
  int nr;
348
340
  char *fmt = RSTRING_PTR(op[1]);
349
341
  int ndiv = NUM2INT(op[2]);
342
+ int usec = ts->tv_nsec / 1000;
350
343
 
351
344
  nr = snprintf(buf, sizeof(buf), fmt,
352
- (int)tv->tv_sec, (int)(tv->tv_usec / ndiv));
345
+ (int)ts->tv_sec, (int)(usec / ndiv));
353
346
  assert(nr > 0 && nr < (int)sizeof(buf));
354
347
  rb_str_buf_cat(c->log_buf, buf, nr);
355
348
  }
356
349
 
357
350
  static void append_request_time_fmt(struct clogger *c, const VALUE *op)
358
351
  {
359
- struct timeval now, d;
352
+ 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)");
360
357
 
361
- gettimeofday(&now, NULL);
362
- timersub(&now, &c->tv_start, &d);
363
- append_tv(c, op, &d);
358
+ clock_diff(&now, &c->ts_start);
359
+ append_ts(c, op, &now);
364
360
  }
365
361
 
366
362
  static void append_time_fmt(struct clogger *c, const VALUE *op)
367
363
  {
368
- struct timeval now;
364
+ struct timespec now;
365
+ int r = clock_gettime(CLOCK_REALTIME, &now);
369
366
 
370
- gettimeofday(&now, NULL);
371
- append_tv(c, op, &now);
367
+ if (unlikely(r != 0))
368
+ rb_sys_fail("clock_gettime(CLOCK_REALTIME)");
369
+ append_ts(c, op, &now);
372
370
  }
373
371
 
374
372
  static void append_request_uri(struct clogger *c)
@@ -588,12 +586,35 @@ static VALUE cwrite(struct clogger *c)
588
586
  return Qnil;
589
587
  }
590
588
 
589
+ static void init_logger(struct clogger *c, VALUE path)
590
+ {
591
+ ID id;
592
+
593
+ if (!NIL_P(path) && !NIL_P(c->logger))
594
+ rb_raise(rb_eArgError, ":logger and :path are independent");
595
+ if (!NIL_P(path)) {
596
+ VALUE ab = rb_str_new2("ab");
597
+ id = rb_intern("open");
598
+ c->logger = rb_funcall(rb_cFile, id, 2, path, ab);
599
+ }
600
+
601
+ id = rb_intern("sync=");
602
+ if (rb_respond_to(c->logger, id))
603
+ rb_funcall(c->logger, id, 1, Qtrue);
604
+
605
+ id = rb_intern("fileno");
606
+ if (rb_respond_to(c->logger, id))
607
+ c->fd = raw_fd(rb_funcall(c->logger, id, 0));
608
+ }
609
+
591
610
  /**
592
611
  * call-seq:
593
612
  * Clogger.new(app, :logger => $stderr, :format => string) => obj
594
613
  *
595
614
  * Creates a new Clogger object that wraps +app+. +:logger+ may
596
615
  * be any object that responds to the "<<" method with a string argument.
616
+ * If +:logger:+ is a string, it will be treated as a path to a
617
+ * File that will be opened in append mode.
597
618
  */
598
619
  static VALUE clogger_init(int argc, VALUE *argv, VALUE self)
599
620
  {
@@ -609,12 +630,9 @@ static VALUE clogger_init(int argc, VALUE *argv, VALUE self)
609
630
  if (TYPE(o) == T_HASH) {
610
631
  VALUE tmp;
611
632
 
633
+ tmp = rb_hash_aref(o, ID2SYM(rb_intern("path")));
612
634
  c->logger = rb_hash_aref(o, ID2SYM(rb_intern("logger")));
613
- if (!NIL_P(c->logger)) {
614
- rb_rescue(obj_enable_sync, c->logger, NULL, 0);
615
- tmp = rb_rescue(obj_fileno, c->logger, NULL, 0);
616
- c->fd = raw_fd(tmp);
617
- }
635
+ init_logger(c, tmp);
618
636
 
619
637
  tmp = rb_hash_aref(o, ID2SYM(rb_intern("format")));
620
638
  if (!NIL_P(tmp))
@@ -710,7 +728,7 @@ static VALUE ccall(struct clogger *c, VALUE env)
710
728
  {
711
729
  VALUE rv;
712
730
 
713
- gettimeofday(&c->tv_start, NULL);
731
+ clock_gettime(CLOCK_MONOTONIC, &c->ts_start);
714
732
  c->env = env;
715
733
  c->cookies = Qfalse;
716
734
  rv = rb_funcall(c->app, call_id, 1, env);
@@ -800,9 +818,17 @@ static VALUE clogger_init_copy(VALUE clone, VALUE orig)
800
818
 
801
819
  #define CONST_GLOBAL_STR(val) CONST_GLOBAL_STR2(val, #val)
802
820
 
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
827
+
803
828
  static VALUE to_path(VALUE self)
804
829
  {
805
- struct clogger *c = clogger_get(RSTRUCT_PTR(self)[0]);
830
+ VALUE my_clogger = ToPath_clogger(self);
831
+ struct clogger *c = clogger_get(my_clogger);
806
832
  VALUE path = rb_funcall(c->body, to_path_id, 0);
807
833
  struct stat sb;
808
834
  int rv;
@@ -879,4 +905,7 @@ void Init_clogger_ext(void)
879
905
  cHeaderHash = rb_const_get(tmp, rb_intern("HeaderHash"));
880
906
  cToPath = rb_const_get(cClogger, rb_intern("ToPath"));
881
907
  rb_define_method(cToPath, "to_path", to_path, 0);
908
+ #ifndef RSTRUCT_PTR
909
+ clogger_id = rb_intern("clogger");
910
+ #endif
882
911
  }
@@ -13,6 +13,10 @@ 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'
18
+ have_func('CLOCK_MONOTONIC', 'time.h')
19
+ end
16
20
  have_func('localtime_r', 'time.h') or raise "localtime_r needed"
17
21
  have_func('gmtime_r', 'time.h') or raise "gmtime_r needed"
18
22
  have_func('rb_str_set_len', 'ruby.h')
@@ -11,11 +11,13 @@
11
11
  #ifndef RARRAY_LEN
12
12
  # define RARRAY_LEN(s) (RARRAY(s)->len)
13
13
  #endif
14
- #ifndef RSTRUCT_PTR
15
- # define RSTRUCT_PTR(s) (RSTRUCT(s)->ptr)
16
- #endif
17
- #ifndef RSTRUCT_LEN
18
- # define RSTRUCT_LEN(s) (RSTRUCT(s)->len)
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
19
21
  #endif
20
22
 
21
23
  #ifndef HAVE_RB_STR_SET_LEN
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.5.0
8
- VERSION = '0.5.0'
7
+ # the version of Clogger, currently 0.6.0
8
+ VERSION = '0.6.0'
9
9
 
10
10
  # :stopdoc:
11
11
  OP_LITERAL = 0
@@ -57,7 +57,7 @@ private
57
57
  path_info query_string script_name
58
58
  server_name server_port
59
59
  auth_type gateway_interface server_software path_translated
60
- ).join('|') << ')\z').freeze
60
+ ).join('|') << ')\z')
61
61
 
62
62
  SCAN = /([^$]*)(\$+(?:env\{\w+(?:\.[\w\.]+)?\}|
63
63
  e\{[^\}]+\}|
@@ -73,28 +73,28 @@ private
73
73
 
74
74
  unless tok.nil?
75
75
  if tok.sub!(/\A(\$+)\$/, '$')
76
- rv << [ OP_LITERAL, $1.dup ]
76
+ rv << [ OP_LITERAL, $1 ]
77
77
  end
78
78
 
79
79
  compat = ALIASES[tok] and tok = compat
80
80
 
81
81
  case tok
82
82
  when /\A(\$*)\z/
83
- rv << [ OP_LITERAL, $1.dup ]
83
+ rv << [ OP_LITERAL, $1 ]
84
84
  when /\A\$env\{(\w+(?:\.[\w\.]+))\}\z/
85
- rv << [ OP_REQUEST, $1.freeze ]
85
+ rv << [ OP_REQUEST, $1 ]
86
86
  when /\A\$e\{([^\}]+)\}\z/
87
- rv << [ OP_EVAL, $1.dup ]
87
+ rv << [ OP_EVAL, $1 ]
88
88
  when /\A\$cookie_(\w+)\z/
89
- rv << [ OP_COOKIE, $1.dup.freeze ]
89
+ rv << [ OP_COOKIE, $1 ]
90
90
  when CGI_ENV, /\A\$(http_\w+)\z/
91
- rv << [ OP_REQUEST, $1.upcase.freeze ]
91
+ rv << [ OP_REQUEST, $1.upcase ]
92
92
  when /\A\$sent_http_(\w+)\z/
93
- rv << [ OP_RESPONSE, $1.downcase.tr('_','-').freeze ]
93
+ rv << [ OP_RESPONSE, $1.downcase.tr('_','-') ]
94
94
  when /\A\$time_local\{([^\}]+)\}\z/
95
- rv << [ OP_TIME_LOCAL, $1.dup ]
95
+ rv << [ OP_TIME_LOCAL, $1 ]
96
96
  when /\A\$time_utc\{([^\}]+)\}\z/
97
- rv << [ OP_TIME_UTC, $1.dup ]
97
+ rv << [ OP_TIME_UTC, $1 ]
98
98
  when /\A\$time\{(\d+)\}\z/
99
99
  rv << [ OP_TIME, *usec_conv_pair(tok, $1.to_i) ]
100
100
  when /\A\$request_time\{(\d+)\}\z/
@@ -7,19 +7,19 @@ class Clogger
7
7
  # common log format used by Apache:
8
8
  # http://httpd.apache.org/docs/2.2/logs.html
9
9
  Common = "$remote_addr - $remote_user [$time_local] " \
10
- '"$request" $status $response_length'.freeze
10
+ '"$request" $status $response_length'
11
11
 
12
12
  # combined log format used by Apache:
13
13
  # http://httpd.apache.org/docs/2.2/logs.html
14
- Combined = %Q|#{Common} "$http_referer" "$http_user_agent"|.freeze
14
+ Combined = %Q|#{Common} "$http_referer" "$http_user_agent"|
15
15
 
16
16
  # combined log format used by nginx:
17
17
  # http://wiki.nginx.org/NginxHttpLogModule
18
- NginxCombined = Combined.gsub(/response_length/, 'body_bytes_sent').freeze
18
+ NginxCombined = Combined.gsub(/response_length/, 'body_bytes_sent')
19
19
 
20
20
  # log format used by Rack 1.0
21
21
  Rack_1_0 = "$ip - $remote_user [$time_local{%d/%b/%Y %H:%M:%S}] " \
22
- '"$request" $status $response_length $request_time{4}'.freeze
22
+ '"$request" $status $response_length $request_time{4}'
23
23
  end
24
24
 
25
25
  end
data/lib/clogger/pure.rb CHANGED
@@ -14,7 +14,12 @@ class Clogger
14
14
 
15
15
  @app = app
16
16
  @logger = opts[:logger]
17
- (@logger.sync = true) rescue nil
17
+ path = opts[:path]
18
+ path && @logger and
19
+ raise ArgumentError, ":logger and :path are independent"
20
+ path and @logger = File.open(path, "ab")
21
+
22
+ @logger.sync = true if @logger.respond_to?(:sync=)
18
23
  @fmt_ops = compile_format(opts[:format] || Format::Common, opts)
19
24
  @wrap_body = need_wrap_body?(@fmt_ops)
20
25
  @reentrant = opts[:reentrant]
@@ -69,7 +74,7 @@ class Clogger
69
74
  end
70
75
 
71
76
  def fileno
72
- @logger.fileno rescue nil
77
+ @logger.respond_to?(:fileno) ? @logger.fileno : nil
73
78
  end
74
79
 
75
80
  private
@@ -138,7 +143,7 @@ private
138
143
  time_format(t.to_i, (t - t.to_i) * 1000000, op[1], op[2])
139
144
  when OP_TIME
140
145
  t = Time.now
141
- time_format(t.sec, t.usec, op[1], op[2])
146
+ time_format(t.to_i, t.usec, op[1], op[2])
142
147
  when OP_COOKIE
143
148
  (env['rack.request.cookie_hash'][op[1]] rescue "-") || "-"
144
149
  else
data/test/test_clogger.rb CHANGED
@@ -3,6 +3,7 @@ $stderr.sync = $stdout.sync = true
3
3
  require "test/unit"
4
4
  require "date"
5
5
  require "stringio"
6
+ require "tempfile"
6
7
 
7
8
  require "rack"
8
9
 
@@ -240,32 +241,52 @@ class TestClogger < Test::Unit::TestCase
240
241
  str = StringIO.new
241
242
  app = lambda { |env| [ 200, {}, [] ] }
242
243
  cl = Clogger.new(app, :logger => str, :format => '$msec')
244
+ a = Time.now.to_f - 0.001
243
245
  status, header, bodies = cl.call(@req)
244
246
  assert_match %r(\A\d+\.\d{3}\n\z), str.string
247
+ b = Time.now.to_f + 0.001
248
+ logged = str.string.to_f
249
+ assert logged >= a, "#{logged} >= #{a}"
250
+ assert logged <= b, "#{logged} <= #{b}"
245
251
  end
246
252
 
247
253
  def test_usec
248
254
  str = StringIO.new
249
255
  app = lambda { |env| [ 200, {}, [] ] }
250
256
  cl = Clogger.new(app, :logger => str, :format => '$usec')
257
+ a = Time.now.to_f - 0.000001
251
258
  status, header, bodies = cl.call(@req)
252
259
  assert_match %r(\A\d+\.\d{6}\n\z), str.string
260
+ b = Time.now.to_f + 0.000001
261
+ logged = str.string.to_f
262
+ assert logged >= a, "#{logged} >= #{a}"
263
+ assert logged <= b, "#{logged} <= #{b}"
253
264
  end
254
265
 
255
266
  def test_time_0
256
267
  str = StringIO.new
257
268
  app = lambda { |env| [ 200, {}, [] ] }
258
269
  cl = Clogger.new(app, :logger => str, :format => '$time{0}')
270
+ a = Time.now.to_f - 1
259
271
  status, header, bodies = cl.call(@req)
260
272
  assert_match %r(\A\d+\n\z), str.string
273
+ b = Time.now.to_f + 1
274
+ logged = str.string.to_f
275
+ assert logged >= a, "#{logged} >= #{a}"
276
+ assert logged <= b, "#{logged} <= #{b}"
261
277
  end
262
278
 
263
279
  def test_time_1
264
280
  str = StringIO.new
265
281
  app = lambda { |env| [ 200, {}, [] ] }
266
282
  cl = Clogger.new(app, :logger => str, :format => '$time{1}')
283
+ a = Time.now.to_f - 0.5
267
284
  status, header, bodies = cl.call(@req)
268
285
  assert_match %r(\A\d+\.\d\n\z), str.string
286
+ b = Time.now.to_f + 0.5
287
+ logged = str.string.to_f
288
+ assert logged >= a, "#{logged} >= #{a}"
289
+ assert logged <= b, "#{logged} <= #{b}"
269
290
  end
270
291
 
271
292
  def test_request_length
@@ -629,4 +650,31 @@ class TestClogger < Test::Unit::TestCase
629
650
  end
630
651
  end if RUBY_PLATFORM =~ /linux/ && File.readable?(LINUX_PROC_PID_STATUS)
631
652
 
653
+ def test_path_open_file
654
+ tmp = Tempfile.new('test_clogger')
655
+ app = lambda { |env| [ 200, {}, [] ] }
656
+ app = Clogger.new(app, :format => '$status', :path => tmp.path)
657
+ assert_kind_of Integer, app.fileno
658
+ assert app.fileno != tmp.fileno
659
+ status, headers, body = app.call(@req)
660
+ assert_equal "200\n", tmp.read
661
+ end
662
+
663
+ def test_path_logger_conflict
664
+ tmp = Tempfile.new('test_clogger')
665
+ app = lambda { |env| [ 200, {}, [] ] }
666
+ assert_raises(ArgumentError) {
667
+ Clogger.new(app, :logger=> $stderr, :path => tmp.path)
668
+ }
669
+ end
670
+
671
+ def test_request_time
672
+ s = []
673
+ app = lambda { |env| sleep(0.1) ; [302, [], [] ] }
674
+ cl = Clogger.new(app, :logger => s, :format => "$request_time")
675
+ status, headers, body = cl.call(@req)
676
+ assert_nothing_raised { body.each { |x| } ; body.close }
677
+ assert s[-1].to_f >= 0.100
678
+ assert s[-1].to_f <= 0.110
679
+ end
632
680
  end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ hash: 7
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - cloggers
@@ -9,22 +15,40 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-06-06 00:00:00 +00:00
18
+ date: 2010-12-25 00:00:00 +00:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: rack
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">"
22
28
  - !ruby/object:Gem::Version
29
+ hash: 25
30
+ segments:
31
+ - 0
32
+ - 9
23
33
  version: "0.9"
24
- version:
25
- description: |-
26
- Clogger is Rack middleware for logging HTTP requests. The log format
27
- is customizable so you can specify exactly which fields to log.
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: wrongdoc
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 15
45
+ segments:
46
+ - 1
47
+ - 0
48
+ version: "1.0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: == DESCRIPTION
28
52
  email: clogger@librelist.com
29
53
  executables: []
30
54
 
@@ -39,15 +63,18 @@ extra_rdoc_files:
39
63
  - lib/clogger/pure.rb
40
64
  - ext/clogger_ext/clogger.c
41
65
  - LICENSE
66
+ - LATEST
42
67
  files:
43
68
  - .document
44
69
  - .gitignore
45
70
  - .manifest
71
+ - .wrongdoc.yml
46
72
  - COPYING
47
73
  - ChangeLog
48
74
  - GIT-VERSION-FILE
49
75
  - GIT-VERSION-GEN
50
76
  - GNUmakefile
77
+ - LATEST
51
78
  - LICENSE
52
79
  - NEWS
53
80
  - README
@@ -68,28 +95,35 @@ licenses: []
68
95
 
69
96
  post_install_message:
70
97
  rdoc_options:
71
- - -Na
72
98
  - -t
73
- - Clogger - configurable request logging for Rack
99
+ - \Clogger - configurable request logging for Rack
100
+ - -W
101
+ - http://git.bogomips.org/cgit/clogger.git/tree/%s
74
102
  require_paths:
75
103
  - lib
76
104
  - ext
77
105
  required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
78
107
  requirements:
79
108
  - - ">="
80
109
  - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
81
113
  version: "0"
82
- version:
83
114
  required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
84
116
  requirements:
85
117
  - - ">="
86
118
  - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
87
122
  version: "0"
88
- version:
89
123
  requirements: []
90
124
 
91
125
  rubyforge_project: clogger
92
- rubygems_version: 1.3.5
126
+ rubygems_version: 1.3.7
93
127
  signing_key:
94
128
  specification_version: 3
95
129
  summary: configurable request logging for Rack