clogger 2.0.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 85af41cf4cb499a42ed7dbd0fa83176b587e7897
4
- data.tar.gz: 363e963d851ffc22fc5947b859eac866c8c4f129
2
+ SHA256:
3
+ metadata.gz: aa136dd8c34021aa1fe06bc527ddee6f0b2e3f1c6690292bba0566938efc11f4
4
+ data.tar.gz: c91b0dcb15b374bf6d89812b0dbcb002e9811b94a537465d96d5639191c55ab3
5
5
  SHA512:
6
- metadata.gz: be050e0aa75fa61a11505d0bc677cfbcbbcf7675ecb87fed56e511636db0cb85fc76cfda5e041d8c8dfb2f46c8cae14e0a3e9f76e5fb1d6812eedd156001c56e
7
- data.tar.gz: 22da33f482565c5d9fc63d3f6a3279ba3c02dac61d634cad93e5221132831d30a0cea0ba02a829be984061bfa0c28b96edd6ee6ad0c5762c6f27e5cbdf17fca9
6
+ metadata.gz: a3dc7e9f494fcd6acc52c82ba5f1c50d0bead5b5042189766f48f0229e595682c704f054a4d45ac5857a77a98c0c9d09e53c333f63a42e5c1232a2af9e1c1fe3
7
+ data.tar.gz: e72490ade869362cca1dd0df4cbd56c93c08a45f5baf32e88fd38b9a806b043286d1d58adaf3e31dae200a1f61f4e002b7f3e7bea15174d599af897609759cb2
@@ -1,7 +1,16 @@
1
1
  ---
2
- rdoc_url: http://clogger.bogomips.org/
3
- cgit_url: http://bogomips.org/clogger.git
4
- git_url: git://bogomips.org/clogger.git
5
- public_email: clogger-public@bogomips.org
6
- private_email: clogger@bogomips.org
7
- ml_url: http://bogomips.org/clogger-public/
2
+ rdoc_url: https://yhbt.net/clogger/
3
+ cgit_url: https://yhbt.net/clogger.git
4
+ git_url: git://yhbt.net/clogger.git
5
+ public_email: clogger-public@yhbt.net
6
+ ml_url:
7
+ - https://yhbt.net/clogger-public/
8
+ - http://ou63pmih66umazou.onion/clogger-public/
9
+ - imaps://news.public-inbox.org/inbox.comp.lang.ruby.clogger.0
10
+ - imap://ou63pmih66umazou.onion/inbox.comp.lang.ruby.clogger.0
11
+ - nntps://news.public-inbox.org/inbox.comp.lang.ruby.clogger
12
+ - nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.clogger
13
+ source_code:
14
+ - git clone git://yhbt.net/clogger.git
15
+ - git clone https://yhbt.net/clogger.git
16
+ - torsocks git clone http://ou63pmih66umazou.onion/clogger.git
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v2.0.1
4
+ DEF_VER=v2.3.0
5
5
 
6
6
  LF='
7
7
  '
@@ -1,5 +1,5 @@
1
1
  all::
2
- RSYNC_DEST := clogger.bogomips.org:/srv/clogger/
2
+ RSYNC_DEST := yhbt.net:/srv/yhbt/clogger/
3
3
  rfpackage := clogger
4
4
  include pkg.mk
5
5
  test-ext:
data/LICENSE CHANGED
@@ -3,7 +3,7 @@ revision control for names and email addresses of all of them.
3
3
 
4
4
  You can redistribute it and/or modify it under the terms of the GNU
5
5
  Lesser General Public License (LGPL) as published by the Free Software
6
- Foundation, version {2.1}[http://www.gnu.org/licenses/lgpl-2.1.txt] or
6
+ Foundation, version {2.1}[https://www.gnu.org/licenses/lgpl-2.1.txt] or
7
7
  (at your option) any later version.
8
8
 
9
9
  clogger is distributed in the hope that it will be useful, but WITHOUT
@@ -12,5 +12,4 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12
12
  License for more details.
13
13
 
14
14
  You should have received a copy of the GNU Lesser General Public License
15
- along with this library; if not, write to the Free Software
16
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
15
+ along with this library; if not, see https://www.gnu.org/licenses/
data/README CHANGED
@@ -69,10 +69,12 @@ that receives a "<<" method:
69
69
  * $request_uri - the URI requested ($path_info?$query_string)
70
70
  * $request - the first line of the HTTP request
71
71
  ($request_method $request_uri $http_version)
72
- * $request_time, $request_time{PRECISION} - time taken for request
73
- (including response body iteration). PRECISION defaults to 3
74
- (milliseconds) if not specified but may be specified anywhere from
75
- 0(seconds) to 6(microseconds).
72
+ * $request_time, $request_time{PRECISION}, $request_time{POWER,PRECISION} -
73
+ time taken for request (including response body iteration). PRECISION
74
+ defaults to 3 (milliseconds) if not specified but may be specified
75
+ anywhere from 0(seconds) to 6(microseconds). POWER will raise the time to
76
+ the provided power of 10, useful for converting to micro- or nanoseconds.
77
+ POWER defaults to 0 if not specified but may be specified any from 0 to 9
76
78
  * $time_iso8601 - current local time in ISO 8601 format,
77
79
  e.g. "1970-01-01T00:00:00+00:00"
78
80
  * $time_local - current local time in Apache log format,
@@ -87,39 +89,51 @@ that receives a "<<" method:
87
89
  * $ip - X-Forwarded-For request header if available, $remote_addr if not
88
90
  * $pid - process ID of the current process
89
91
  * $e{Thread.current} - Thread processing the request
90
- * $e{Actor.current} - Actor processing the request (Revactor or Rubinius)
92
+ * $e{Fiber.current} - Fiber processing the request
91
93
  * $env{variable_name} - any Rack environment variable (e.g. rack.url_scheme)
92
94
 
93
95
  == REQUIREMENTS
94
96
 
95
- * {Ruby}[http://www.ruby-lang.org/], {Rack}[http://rack.github.io/]
97
+ * {Ruby}[https://www.ruby-lang.org/], {Rack}[https://rack.github.io/]
96
98
 
97
99
  == DEVELOPMENT
98
100
 
99
101
  The latest development happens in git and is published to the following:
100
102
 
101
- git://bogomips.org/clogger.git
102
- git://repo.or.cz/clogger.git
103
+ git clone https://yhbt.net/clogger.git
104
+ git clone git://repo.or.cz/clogger.git
103
105
 
104
106
  You may also browse and download snapshot tarballs:
105
107
 
106
- * http://bogomips.org/clogger.git (cgit)
108
+ * https://yhbt.net/clogger.git
107
109
  * http://repo.or.cz/w/clogger.git (gitweb)
108
110
 
109
- The mailing list (see below) is central for coordination and
110
- development. Patches should always be sent inline
111
- (git format-patch -M + git send-email) so we can reply to them inline.
111
+ We use email for coordination and development, see below:
112
112
 
113
113
  == CONTACT
114
114
 
115
115
  All feedback (bug reports, user/development discussion, patches, pull
116
- requests) go to the public mailing list.
116
+ requests) is done via publicly-archived email:
117
117
 
118
- * mailto:clogger-public@bogomips.org
118
+ * https://yhbt.net/clogger-public/
119
+ * imaps://news.public-inbox.org/inbox.comp.lang.ruby.clogger.0
120
+ * nntps://news.public-inbox.org/inbox.comp.lang.ruby.clogger
119
121
 
120
- Do not send HTML mail or attachments. Do not top post.
122
+ Tor users may also access HTTP, IMAP, and NNTP archives via .onion:
121
123
 
122
- Homepage: http://clogger.bogomips.org/
124
+ * http://ou63pmih66umazou.onion/clogger-public/
125
+ * imap://ou63pmih66umazou.onion/inbox.comp.lang.ruby.clogger.0
126
+ * nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.clogger
127
+
128
+ AUTH=ANONYMOUS is supported for IMAP and IMAPS, and any
129
+ username + password will work.
130
+
131
+ No subscription or real names will ever be required to email us.
132
+ Do not send HTML email, do not top post.
133
+
134
+ * mailto:clogger-public@yhbt.net
135
+
136
+ Homepage: https://yhbt.net/clogger/
123
137
 
124
138
  == INSTALL
125
139
 
@@ -1,25 +1,23 @@
1
- ENV["VERSION"] or abort "VERSION= must be specified"
2
- manifest = File.readlines('.manifest').map! { |x| x.chomp! }
3
- require 'olddoc'
4
- extend Olddoc::Gemspec
5
- name, summary, title = readme_metadata
1
+ manifest = File.exist?('.manifest') ?
2
+ IO.readlines('.manifest').map!(&:chomp!) : `git ls-files`.split("\n")
6
3
 
7
4
  Gem::Specification.new do |s|
8
5
  s.name = %q{clogger}
9
- s.version = ENV["VERSION"].dup
10
- s.homepage = Olddoc.config['rdoc_url']
6
+ s.version = (ENV['VERSION'] || '2.1.0').dup
7
+ s.homepage = 'https://yhbt.net/clogger/'
11
8
  s.authors = ["cloggers"]
12
- s.description = readme_description
13
- s.email = %q{clogger@bogomips.org}
14
- s.extra_rdoc_files = extra_rdoc_files(manifest)
9
+ s.summary = 'configurable request logging for Rack'
10
+ s.description = File.read('README').split("\n\n")[1]
11
+ s.email = %q{clogger-public@yhbt.net}
12
+ s.extra_rdoc_files = IO.readlines('.document').map!(&:chomp!).keep_if do |f|
13
+ File.exist?(f)
14
+ end
15
15
  s.files = manifest
16
- s.summary = summary
17
16
  s.test_files = %w(test/test_clogger.rb test/test_clogger_to_path.rb)
18
17
 
19
18
  # HeaderHash wasn't case-insensitive in old versions
20
- s.add_dependency(%q<rack>, ["~> 1.0"])
21
- s.add_development_dependency(%q<olddoc>, "~> 1.0")
19
+ s.add_dependency(%q<rack>, ['>= 1.0', '< 3.0'])
20
+ s.add_development_dependency('test-unit', '~> 3.0')
22
21
  s.extensions = %w(ext/clogger_ext/extconf.rb)
23
-
24
22
  s.licenses = %w(LGPL-2.1+)
25
23
  end
@@ -54,6 +54,9 @@ static ssize_t my_write(int fd, const void *buf, size_t count)
54
54
 
55
55
  return r;
56
56
  }
57
- # define stat(path,buf) my_stat((path),(buf))
58
- # define write(fd,buf,count) my_write((fd),(buf),(count))
57
+ # define nogvl_stat(path,buf) my_stat((path),(buf))
58
+ # define nogvl_write(fd,buf,count) my_write((fd),(buf),(count))
59
+ #else /* !WITHOUT_GVL, for Ruby 1.8 users: */
60
+ # define nogvl_stat(path,buf) stat((path),(buf))
61
+ # define nogvl_write(fd,buf,buf) write((fd),(buf),(count))
59
62
  #endif /* !WITHOUT_GVL */
@@ -1,3 +1,6 @@
1
+ /* quiet deprecation for _BSD_SOURCE and _SVID_SOURCE: */
2
+ #define _DEFAULT_SOURCE 1
3
+
1
4
  #include <ruby.h>
2
5
  #ifdef HAVE_RUBY_IO_H
3
6
  # include <ruby/io.h>
@@ -29,6 +32,7 @@
29
32
  * under.
30
33
  */
31
34
  static clockid_t hopefully_CLOCK_MONOTONIC;
35
+ static VALUE mark_ary;
32
36
 
33
37
  static void check_clock(void)
34
38
  {
@@ -243,7 +247,7 @@ static void write_full(int fd, const char *buf, size_t count)
243
247
  ssize_t r;
244
248
 
245
249
  while (count > 0) {
246
- r = write(fd, buf, count);
250
+ r = nogvl_write(fd, buf, count);
247
251
 
248
252
  if ((size_t)r == count) { /* overwhelmingly likely */
249
253
  return;
@@ -373,12 +377,40 @@ static void append_ts(struct clogger *c, VALUE op, struct timespec *ts)
373
377
  rb_str_buf_cat(c->log_buf, buf, nr);
374
378
  }
375
379
 
380
+ #define NANO_PER_SEC (1000 * 1000 * 1000)
376
381
  static void append_request_time_fmt(struct clogger *c, VALUE op)
377
382
  {
378
383
  struct timespec now;
384
+ unsigned long ipow = NUM2ULONG(rb_ary_entry(op, 3));
379
385
 
380
386
  clock_gettime(hopefully_CLOCK_MONOTONIC, &now);
381
387
  clock_diff(&now, &c->ts_start);
388
+ if (ipow) {
389
+ struct timespec prev;
390
+ unsigned long adj = 1;
391
+ /*
392
+ * n.b. timespec.tv_sec may not be time_t on some platforms,
393
+ * so we use a full timespec struct instead of time_t:
394
+ */
395
+ prev.tv_sec = now.tv_sec;
396
+ do { adj *= 10; } while (--ipow);
397
+ now.tv_sec *= adj;
398
+ now.tv_nsec *= adj;
399
+ if (now.tv_nsec >= NANO_PER_SEC) {
400
+ int64_t add = now.tv_nsec / NANO_PER_SEC;
401
+ now.tv_sec += add;
402
+ now.tv_nsec %= NANO_PER_SEC;
403
+ }
404
+ if (now.tv_sec < prev.tv_sec) { /* overflowed */
405
+ now.tv_nsec = NANO_PER_SEC - 1;
406
+ /*
407
+ * some platforms may use unsigned .tv_sec, but
408
+ * they're not worth supporting, so keep unsigned:
409
+ */
410
+ now.tv_sec = (time_t)(sizeof(now.tv_sec) == 4 ?
411
+ INT_MAX : LONG_MAX);
412
+ }
413
+ }
382
414
  append_ts(c, op, &now);
383
415
  }
384
416
 
@@ -682,6 +714,7 @@ static VALUE cwrite(struct clogger *c)
682
714
 
683
715
  if (c->fd >= 0) {
684
716
  write_full(c->fd, RSTRING_PTR(dst), RSTRING_LEN(dst));
717
+ /* no need for RB_GC_GUARD(dst) here, marked as c->log_buf */
685
718
  } else {
686
719
  VALUE logger = c->logger;
687
720
 
@@ -948,7 +981,7 @@ static VALUE clogger_init_copy(VALUE clone, VALUE orig)
948
981
 
949
982
  #define CONST_GLOBAL_STR2(var, val) do { \
950
983
  g_##var = rb_obj_freeze(rb_str_new(val, sizeof(val) - 1)); \
951
- rb_global_variable(&g_##var); \
984
+ rb_ary_push(mark_ary, g_##var); \
952
985
  } while (0)
953
986
 
954
987
  #define CONST_GLOBAL_STR(val) CONST_GLOBAL_STR2(val, #val)
@@ -961,14 +994,23 @@ static VALUE clogger_init_copy(VALUE clone, VALUE orig)
961
994
  * used to delegate +:to_path+ checks for Rack webservers that optimize
962
995
  * static file serving
963
996
  */
964
- static VALUE respond_to(VALUE self, VALUE method)
997
+ static VALUE respond_to(int argc, VALUE *argv, VALUE self)
965
998
  {
966
999
  struct clogger *c = clogger_get(self);
967
- ID id = rb_to_id(method);
1000
+ VALUE method, include_all;
1001
+ ID id;
968
1002
 
1003
+ rb_scan_args(argc, argv, "11", &method, &include_all);
1004
+ id = rb_to_id(method);
969
1005
  if (close_id == id)
970
1006
  return Qtrue;
971
- return rb_respond_to(c->body, id);
1007
+
1008
+ #ifdef HAVE_RB_OBJ_RESPOND_TO
1009
+ return rb_obj_respond_to(c->body, id, RTEST(include_all));
1010
+ #endif
1011
+ if (argc == 1)
1012
+ return rb_respond_to(c->body, id);
1013
+ return rb_funcallv(c->body, respond_to_id, argc, argv);
972
1014
  }
973
1015
 
974
1016
  /*
@@ -993,7 +1035,7 @@ static VALUE to_path(VALUE self)
993
1035
  if (sscanf(cpath, "/dev/fd/%u", &devfd) == 1)
994
1036
  rv = fstat((int)devfd, &sb);
995
1037
  else
996
- rv = stat(cpath, &sb);
1038
+ rv = nogvl_stat(cpath, &sb);
997
1039
 
998
1040
  /*
999
1041
  * calling this method implies the web server will bypass
@@ -1014,6 +1056,9 @@ void Init_clogger_ext(void)
1014
1056
  {
1015
1057
  VALUE tmp;
1016
1058
 
1059
+ mark_ary = rb_ary_new();
1060
+ rb_global_variable(&mark_ary);
1061
+
1017
1062
  check_clock();
1018
1063
 
1019
1064
  write_id = rb_intern("write");
@@ -1039,7 +1084,7 @@ void Init_clogger_ext(void)
1039
1084
  rb_define_method(cClogger, "wrap_body?", clogger_wrap_body, 0);
1040
1085
  rb_define_method(cClogger, "reentrant?", clogger_reentrant, 0);
1041
1086
  rb_define_method(cClogger, "to_path", to_path, 0);
1042
- rb_define_method(cClogger, "respond_to?", respond_to, 1);
1087
+ rb_define_method(cClogger, "respond_to?", respond_to, -1);
1043
1088
  rb_define_method(cClogger, "body", body, 0);
1044
1089
  CONST_GLOBAL_STR(REMOTE_ADDR);
1045
1090
  CONST_GLOBAL_STR(HTTP_X_FORWARDED_FOR);
@@ -1059,4 +1104,6 @@ void Init_clogger_ext(void)
1059
1104
  tmp = rb_const_get(rb_cObject, rb_intern("Rack"));
1060
1105
  tmp = rb_const_get(tmp, rb_intern("Utils"));
1061
1106
  cHeaderHash = rb_const_get(tmp, rb_intern("HeaderHash"));
1107
+
1108
+ rb_obj_freeze(mark_ary);
1062
1109
  }
@@ -22,6 +22,7 @@ begin
22
22
  have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
23
23
  have_func('rb_thread_blocking_region', 'ruby.h')
24
24
  have_func('rb_thread_io_blocking_region', 'ruby.h')
25
+ have_func('rb_obj_respond_to', 'ruby/intern.h')
25
26
  create_makefile('clogger_ext')
26
27
  rescue Object => err
27
28
  warn "E: #{err.inspect}"
@@ -51,7 +51,7 @@ private
51
51
 
52
52
  SCAN = /([^$]*)(\$+(?:env\{\w+(?:\.[\w\.]+)?\}|
53
53
  e\{[^\}]+\}|
54
- (?:request_)?time\{\d+\}|
54
+ (?:request_)?time\{\d+(?:,\d+)?\}|
55
55
  time_(?:utc|local)\{[^\}]+\}|
56
56
  \w*))?([^$]*)/x
57
57
 
@@ -92,7 +92,14 @@ private
92
92
  when /\A\$time\{(\d+)\}\z/
93
93
  rv << [ OP_TIME, *usec_conv_pair(tok, $1.to_i) ]
94
94
  when /\A\$request_time\{(\d+)\}\z/
95
- rv << [ OP_REQUEST_TIME, *usec_conv_pair(tok, $1.to_i) ]
95
+ rv << [ OP_REQUEST_TIME, *usec_conv_pair(tok, $1.to_i), 0 ]
96
+ when /\A\$request_time\{(\d+),(\d+)\}\z/
97
+ ipow = $1.to_i
98
+ prec = $2.to_i
99
+ if ipow > 9 # nanosecond precision is the highest POSIX goes
100
+ raise ArgumentError, "#{tok}: too big: #{ipow} (max=9)"
101
+ end
102
+ rv << [ OP_REQUEST_TIME, *usec_conv_pair(tok, prec), ipow ]
96
103
  else
97
104
  tok_sym = tok[1..-1].to_sym
98
105
  if special_code = SPECIAL_VARS[tok_sym]
@@ -5,12 +5,12 @@ class Clogger
5
5
  # predefined log formats in wide use
6
6
  module Format
7
7
  # common log format used by Apache:
8
- # http://httpd.apache.org/docs/2.2/logs.html
8
+ # https://httpd.apache.org/docs/2.4/logs.html
9
9
  Common = "$remote_addr - $remote_user [$time_local] " \
10
10
  '"$request" $status $response_length'
11
11
 
12
12
  # combined log format used by Apache:
13
- # http://httpd.apache.org/docs/2.2/logs.html
13
+ # https://httpd.apache.org/docs/2.4/logs.html
14
14
  Combined = %Q|#{Common} "$http_referer" "$http_user_agent"|
15
15
 
16
16
  # combined log format used by nginx:
@@ -6,7 +6,7 @@
6
6
  class Clogger
7
7
 
8
8
  attr_accessor :env, :status, :headers, :body
9
- attr_writer :body_bytes_sent
9
+ attr_writer :body_bytes_sent, :start
10
10
 
11
11
  def initialize(app, opts = {})
12
12
  # trigger autoload to avoid thread-safety issues later on
@@ -28,10 +28,10 @@ class Clogger
28
28
  end
29
29
 
30
30
  def call(env)
31
- @start = Time.now
31
+ start = mono_now
32
32
  resp = @app.call(env)
33
33
  unless resp.instance_of?(Array) && resp.size == 3
34
- log(env, 500, {})
34
+ log(env, 500, {}, start)
35
35
  raise TypeError, "app response not a 3 element Array: #{resp.inspect}"
36
36
  end
37
37
  status, headers, body = resp
@@ -39,20 +39,21 @@ class Clogger
39
39
  if @wrap_body
40
40
  @reentrant = env['rack.multithread'] if @reentrant.nil?
41
41
  wbody = @reentrant ? self.dup : self
42
+ wbody.start = start
42
43
  wbody.env = env
43
44
  wbody.status = status
44
45
  wbody.headers = headers
45
46
  wbody.body = body
46
47
  return [ status, headers, wbody ]
47
48
  end
48
- log(env, status, headers)
49
+ log(env, status, headers, start)
49
50
  [ status, headers, body ]
50
51
  end
51
52
 
52
53
  def each
53
54
  @body_bytes_sent = 0
54
55
  @body.each do |part|
55
- @body_bytes_sent += Rack::Utils.bytesize(part)
56
+ @body_bytes_sent += part.bytesize
56
57
  yield part
57
58
  end
58
59
  self
@@ -60,8 +61,8 @@ class Clogger
60
61
 
61
62
  def close
62
63
  @body.close if @body.respond_to?(:close)
63
- ensure
64
- log(@env, @status, @headers)
64
+ ensure
65
+ log(@env, @status, @headers)
65
66
  end
66
67
 
67
68
  def reentrant?
@@ -76,8 +77,8 @@ class Clogger
76
77
  @logger.respond_to?(:fileno) ? @logger.fileno : nil
77
78
  end
78
79
 
79
- def respond_to?(m)
80
- :close == m.to_sym || @body.respond_to?(m)
80
+ def respond_to?(method, include_all=false)
81
+ :close == method.to_sym || @body.respond_to?(method, include_all)
81
82
  end
82
83
 
83
84
  def to_path
@@ -153,7 +154,7 @@ private
153
154
  format % [ sec, usec / div ]
154
155
  end
155
156
 
156
- def log(env, status, headers)
157
+ def log(env, status, headers, start = @start)
157
158
  str = @fmt_ops.map { |op|
158
159
  case op[0]
159
160
  when OP_LITERAL; op[1]
@@ -164,7 +165,8 @@ private
164
165
  when OP_TIME_LOCAL; Time.now.strftime(op[1])
165
166
  when OP_TIME_UTC; Time.now.utc.strftime(op[1])
166
167
  when OP_REQUEST_TIME
167
- t = Time.now - @start
168
+ t = mono_now - start
169
+ t = t * (10 ** op[3])
168
170
  time_format(t.to_i, (t - t.to_i) * 1000000, op[1], op[2])
169
171
  when OP_TIME
170
172
  t = Time.now
@@ -184,4 +186,14 @@ private
184
186
  end
185
187
  nil
186
188
  end
189
+
190
+ # favor monotonic clock if possible, and try to use clock_gettime in
191
+ # more recent Rubies since it generates less garbage
192
+ if defined?(Process::CLOCK_MONOTONIC)
193
+ def mono_now; Process.clock_gettime(Process::CLOCK_MONOTONIC); end
194
+ elsif defined?(Process::CLOCK_REALTIME)
195
+ def mono_now; Process.clock_gettime(Process::CLOCK_REALTIME); end
196
+ else
197
+ def mono_now; Time.now.to_f; end
198
+ end
187
199
  end
data/pkg.mk CHANGED
@@ -60,7 +60,7 @@ doc:: .document .olddoc.yml $(pkg_extra) $(PLACEHOLDERS)
60
60
  -find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
61
61
  -find ext -type f -name '*.rbc' -exec rm -f '{}' ';'
62
62
  $(RM) -r doc
63
- $(RDOC) -f oldweb
63
+ $(RDOC) -f dark216
64
64
  $(OLDDOC) merge
65
65
  install -m644 COPYING doc/COPYING
66
66
  install -m644 NEWS doc/NEWS
@@ -147,6 +147,7 @@ class TestClogger < Test::Unit::TestCase
147
147
  req = {
148
148
  'HTTP_HOST' => 'example.com:12345',
149
149
  'HTTP_COOKIE' => cookie,
150
+ 'REMOTE_USER' => 'foo_user',
150
151
  }
151
152
  req = @req.merge(req)
152
153
  body = cl.call(req).last
@@ -154,6 +155,7 @@ class TestClogger < Test::Unit::TestCase
154
155
  body.close
155
156
  str = str.string
156
157
  assert(str.size > 128)
158
+ assert_equal 'foo_user', str.split(' ')[2]
157
159
  assert_match %r["echo and socat \\o/" "#{cookie}" \d+\.\d{3}], str
158
160
  assert_match %r["#{cookie}" \d+\.\d{3} example\.com:12345\n\z], str
159
161
  end
@@ -165,10 +167,11 @@ class TestClogger < Test::Unit::TestCase
165
167
  ary = compile_format(
166
168
  '$remote_addr - $remote_user [$time_local] ' \
167
169
  '"$request" $status $body_bytes_sent "$http_referer" ' \
168
- '"$http_user_agent" "$http_cookie" $request_time ' \
170
+ '"$http_user_agent" "$http_cookie" $request_time $request_time{6,0} ' \
169
171
  '$env{rack.url_scheme}' \
170
172
  "\n")
171
173
  }
174
+
172
175
  expect = [
173
176
  [ Clogger::OP_REQUEST, "REMOTE_ADDR" ],
174
177
  [ Clogger::OP_LITERAL, " - " ],
@@ -188,7 +191,9 @@ class TestClogger < Test::Unit::TestCase
188
191
  [ Clogger::OP_LITERAL, "\" \"" ],
189
192
  [ Clogger::OP_REQUEST, "HTTP_COOKIE" ],
190
193
  [ Clogger::OP_LITERAL, "\" " ],
191
- [ Clogger::OP_REQUEST_TIME, '%d.%03d', 1000 ],
194
+ [ Clogger::OP_REQUEST_TIME, '%d.%03d', 1000, 0],
195
+ [ Clogger::OP_LITERAL, " " ],
196
+ [ Clogger::OP_REQUEST_TIME, '%d', 1, 6],
192
197
  [ Clogger::OP_LITERAL, " " ],
193
198
  [ Clogger::OP_REQUEST, "rack.url_scheme" ],
194
199
  [ Clogger::OP_LITERAL, "\n" ],
@@ -207,6 +212,22 @@ class TestClogger < Test::Unit::TestCase
207
212
  assert_equal "-#{current}-\n", str.string
208
213
  end
209
214
 
215
+ def test_fiber
216
+ begin
217
+ current = Fiber.current.to_s
218
+ rescue NameError => e
219
+ warn "your Ruby does not support fibers #{e}"
220
+ return
221
+ end
222
+ str = StringIO.new
223
+ app = lambda { |env| [ 302, {}, [] ] }
224
+ cl = Clogger.new(app,
225
+ :logger => str,
226
+ :format => "-$e{Fiber.current}-\n")
227
+ status, headers, body = cl.call(@req)
228
+ assert_equal "-#{current}-\n", str.string
229
+ end
230
+
210
231
  def test_pid
211
232
  str = StringIO.new
212
233
  app = lambda { |env| [ 302, {}, [] ] }
@@ -719,6 +740,24 @@ class TestClogger < Test::Unit::TestCase
719
740
  assert s[-1].to_f <= 0.110
720
741
  end
721
742
 
743
+ def test_request_time_with_multiplier
744
+ s = []
745
+ app = lambda { |env| sleep(0.1) ; [302, [], [] ] }
746
+ cl = Clogger.new(app, :logger => s, :format => "$request_time{9,0}")
747
+ status, headers, body = cl.call(@req)
748
+ assert_nothing_raised { body.each { |x| } ; body.close }
749
+ assert s[-1].to_f >= 100000000
750
+ assert s[-1].to_f <= 300000000
751
+ end
752
+
753
+ def test_request_time_with_invalid_multiplier
754
+ s = []
755
+ app = lambda { |env| sleep(0.1) ; [302, [], [] ] }
756
+ assert_raise(ArgumentError) {
757
+ cl = Clogger.new(app, :logger => s, :format => "$request_time{10,0}")
758
+ }
759
+ end
760
+
722
761
  def test_insanely_long_time_format
723
762
  s = []
724
763
  app = lambda { |env| [200, [], [] ] }
@@ -14,6 +14,10 @@ class MyBody < Struct.new(:to_path, :closed)
14
14
  def close
15
15
  self.closed = true
16
16
  end
17
+
18
+ private
19
+ def privtest
20
+ end
17
21
  end
18
22
 
19
23
  class TestCloggerToPath < Test::Unit::TestCase
@@ -59,6 +63,11 @@ class TestCloggerToPath < Test::Unit::TestCase
59
63
  status, headers, body = app.call(@req)
60
64
  assert_instance_of(Clogger, body)
61
65
  check_body(body)
66
+
67
+ assert ! body.respond_to?(:privtest)
68
+ assert body.respond_to?(:privtest, true)
69
+ assert ! body.respond_to?(:privtest, false)
70
+
62
71
  assert logger.string.empty?
63
72
  assert_equal tmp.path, body.to_path
64
73
  body.close
metadata CHANGED
@@ -1,56 +1,59 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - cloggers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-13 00:00:00.000000000 Z
11
+ date: 2020-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '1.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
27
33
  - !ruby/object:Gem::Dependency
28
- name: olddoc
34
+ name: test-unit
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '1.0'
39
+ version: '3.0'
34
40
  type: :development
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '1.0'
46
+ version: '3.0'
41
47
  description: |-
42
48
  clogger is Rack middleware for logging HTTP requests. The log format
43
49
  is customizable so you can specify exactly which fields to log.
44
- email: clogger@bogomips.org
50
+ email: clogger-public@yhbt.net
45
51
  executables: []
46
52
  extensions:
47
53
  - ext/clogger_ext/extconf.rb
48
54
  extra_rdoc_files:
49
55
  - README
50
56
  - NEWS
51
- - lib/clogger.rb
52
- - lib/clogger/format.rb
53
- - lib/clogger/pure.rb
54
57
  - ext/clogger_ext/clogger.c
55
58
  - LICENSE
56
59
  files:
@@ -68,7 +71,6 @@ files:
68
71
  - README
69
72
  - Rakefile
70
73
  - archive/.gitignore
71
- - archive/rfmig.rb
72
74
  - archive/slrnpull.conf
73
75
  - clogger.gemspec
74
76
  - ext/clogger_ext/blocking_helpers.h
@@ -83,7 +85,7 @@ files:
83
85
  - setup.rb
84
86
  - test/test_clogger.rb
85
87
  - test/test_clogger_to_path.rb
86
- homepage: http://clogger.bogomips.org/
88
+ homepage: https://yhbt.net/clogger/
87
89
  licenses:
88
90
  - LGPL-2.1+
89
91
  metadata: {}
@@ -102,8 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
104
  - !ruby/object:Gem::Version
103
105
  version: '0'
104
106
  requirements: []
105
- rubyforge_project:
106
- rubygems_version: 2.4.5
107
+ rubygems_version: 3.0.2
107
108
  signing_key:
108
109
  specification_version: 4
109
110
  summary: configurable request logging for Rack
@@ -1,32 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'find'
3
- require 'fileutils'
4
- rfdir = 'rubyforge.org:/var/www/gforge-projects/clogger/'
5
- newbase = 'http://clogger.bogomips.org/'
6
- refresh = '<meta http-equiv="refresh" content="0; url=%s" />'
7
- old = 'rf.old'
8
- new = 'rf.new'
9
- cmd = %W(rsync -av #{rfdir} #{old}/)
10
- unless File.directory?(old)
11
- system(*cmd) or abort "#{cmd.inspect} failed: #$?"
12
- end
13
-
14
- Find.find(old) do |path|
15
- path =~ /\.html\z/ or next
16
- data = File.read(path)
17
- tmp = path.split(%r{/})
18
- tmp.shift == old or abort "BUG"
19
- dst = "#{new}/#{tmp.join('/')}"
20
-
21
- tmp[-1] = '' if tmp[-1] == "index.html"
22
- url = "#{newbase}#{tmp.join('/')}"
23
- meta = sprintf(refresh, url)
24
- data.sub!(/(<head[^>]*>)/i, "#$1#{meta}")
25
- data.sub!(/(<body[^>]*>)/i,
26
- "#{$1}Redirecting to <a href=\"#{url}\">#{url}</a> ...<br/>")
27
- FileUtils.mkdir_p(File.dirname(dst))
28
- File.open(dst, "w") { |fp| fp.write(data) }
29
- end
30
-
31
- print "Verify results in #{new}/, then run:\n "
32
- puts %W(rsync -av #{new}/ #{rfdir}).join(' ')