clogger 2.0.2 → 2.3.1
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.
- checksums.yaml +5 -5
- data/.olddoc.yml +15 -6
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +1 -1
- data/LICENSE +2 -3
- data/README +30 -16
- data/clogger.gemspec +12 -14
- data/ext/clogger_ext/blocking_helpers.h +5 -2
- data/ext/clogger_ext/clogger.c +55 -7
- data/ext/clogger_ext/extconf.rb +1 -0
- data/lib/clogger.rb +9 -2
- data/lib/clogger/format.rb +2 -2
- data/lib/clogger/pure.rb +4 -3
- data/pkg.mk +3 -2
- data/test/test_clogger.rb +41 -2
- data/test/test_clogger_to_path.rb +9 -0
- metadata +16 -15
- data/archive/rfmig.rb +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 576fb98e7943e4f2ac8b11fa90cd693fd7986b9178bde431c19ccabbc3ddd1ca
|
|
4
|
+
data.tar.gz: 22ed09593fba7cb5af8cfc9e3f431a2398a33a8e760fa6bf855b569a9b8010a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 80bec9f9effd1a976d854d0edf718eb87c03d2880b98f930e7381ddd889fe9b371efab2b52f6e36f5eb65dbb75a06c955e72c2e006fa4c1b22de66dd9e0c454e
|
|
7
|
+
data.tar.gz: 69a4dc1a160ebac95da18310212f2cb5b5c9e5badae56c21dada97823199be242d22c7d46947efd922d03603c033e9e5322b312a5a7b582a10c7e1f39e65ef28
|
data/.olddoc.yml
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
rdoc_url:
|
|
3
|
-
cgit_url:
|
|
4
|
-
git_url: git://
|
|
5
|
-
public_email: clogger-public@
|
|
6
|
-
|
|
7
|
-
|
|
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://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/clogger-public/
|
|
9
|
+
- imaps://news.public-inbox.org/inbox.comp.lang.ruby.clogger.0
|
|
10
|
+
- imap://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.clogger.0
|
|
11
|
+
- nntps://news.public-inbox.org/inbox.comp.lang.ruby.clogger
|
|
12
|
+
- nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.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://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/clogger.git
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
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}[
|
|
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,
|
|
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} -
|
|
73
|
-
(including response body iteration).
|
|
74
|
-
(milliseconds) if not specified but may be specified
|
|
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{
|
|
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}[
|
|
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://
|
|
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
|
-
*
|
|
108
|
+
* https://yhbt.net/clogger.git
|
|
107
109
|
* http://repo.or.cz/w/clogger.git (gitweb)
|
|
108
110
|
|
|
109
|
-
|
|
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)
|
|
116
|
+
requests) is done via publicly-archived email:
|
|
117
117
|
|
|
118
|
-
*
|
|
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
|
-
|
|
122
|
+
Tor users may also access HTTP, IMAP, and NNTP archives via .onion:
|
|
121
123
|
|
|
122
|
-
|
|
124
|
+
* http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/clogger-public/
|
|
125
|
+
* imap://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.clogger.0
|
|
126
|
+
* nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.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
|
|
data/clogger.gemspec
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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[
|
|
10
|
-
s.homepage =
|
|
6
|
+
s.version = (ENV['VERSION'] || '2.1.0').dup
|
|
7
|
+
s.homepage = 'https://yhbt.net/clogger/'
|
|
11
8
|
s.authors = ["cloggers"]
|
|
12
|
-
s.
|
|
13
|
-
s.
|
|
14
|
-
s.
|
|
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>, [
|
|
21
|
-
s.add_development_dependency(
|
|
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
|
|
58
|
-
# define
|
|
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 */
|
data/ext/clogger_ext/clogger.c
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
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
|
|
997
|
+
static VALUE respond_to(int argc, VALUE *argv, VALUE self)
|
|
965
998
|
{
|
|
966
999
|
struct clogger *c = clogger_get(self);
|
|
967
|
-
|
|
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
|
-
|
|
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 =
|
|
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,7 @@ 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
|
+
rb_ary_push(mark_ary, cHeaderHash);
|
|
1108
|
+
|
|
1109
|
+
rb_obj_freeze(mark_ary);
|
|
1062
1110
|
}
|
data/ext/clogger_ext/extconf.rb
CHANGED
|
@@ -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}"
|
data/lib/clogger.rb
CHANGED
|
@@ -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]
|
data/lib/clogger/format.rb
CHANGED
|
@@ -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
|
-
#
|
|
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
|
-
#
|
|
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:
|
data/lib/clogger/pure.rb
CHANGED
|
@@ -53,7 +53,7 @@ class Clogger
|
|
|
53
53
|
def each
|
|
54
54
|
@body_bytes_sent = 0
|
|
55
55
|
@body.each do |part|
|
|
56
|
-
@body_bytes_sent +=
|
|
56
|
+
@body_bytes_sent += part.bytesize
|
|
57
57
|
yield part
|
|
58
58
|
end
|
|
59
59
|
self
|
|
@@ -77,8 +77,8 @@ class Clogger
|
|
|
77
77
|
@logger.respond_to?(:fileno) ? @logger.fileno : nil
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
def respond_to?(
|
|
81
|
-
:close ==
|
|
80
|
+
def respond_to?(method, include_all=false)
|
|
81
|
+
:close == method.to_sym || @body.respond_to?(method, include_all)
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def to_path
|
|
@@ -166,6 +166,7 @@ private
|
|
|
166
166
|
when OP_TIME_UTC; Time.now.utc.strftime(op[1])
|
|
167
167
|
when OP_REQUEST_TIME
|
|
168
168
|
t = mono_now - start
|
|
169
|
+
t = t * (10 ** op[3])
|
|
169
170
|
time_format(t.to_i, (t - t.to_i) * 1000000, op[1], op[2])
|
|
170
171
|
when OP_TIME
|
|
171
172
|
t = Time.now
|
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
|
|
63
|
+
$(RDOC) -f dark216
|
|
64
64
|
$(OLDDOC) merge
|
|
65
65
|
install -m644 COPYING doc/COPYING
|
|
66
66
|
install -m644 NEWS doc/NEWS
|
|
@@ -127,7 +127,8 @@ publish_doc:
|
|
|
127
127
|
-git set-file-times
|
|
128
128
|
$(MAKE) doc
|
|
129
129
|
$(MAKE) doc_gz
|
|
130
|
-
$(RSYNC) -av doc/ $(RSYNC_DEST)/
|
|
130
|
+
$(RSYNC) -av doc/ $(RSYNC_DEST)/ \
|
|
131
|
+
--exclude index.html* --exclude created.rid*
|
|
131
132
|
git ls-files | xargs touch
|
|
132
133
|
endif
|
|
133
134
|
|
data/test/test_clogger.rb
CHANGED
|
@@ -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.
|
|
4
|
+
version: 2.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- cloggers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-05-25 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:
|
|
34
|
+
name: test-unit
|
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
|
30
36
|
requirements:
|
|
31
37
|
- - "~>"
|
|
32
38
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
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: '
|
|
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@
|
|
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:
|
|
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
|
-
|
|
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
|
data/archive/rfmig.rb
DELETED
|
@@ -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(' ')
|