clogger 0.9.0 → 1.0.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 +1 -1
- data/README +5 -4
- data/ext/clogger_ext/clogger.c +85 -3
- data/ext/clogger_ext/extconf.rb +0 -1
- data/lib/clogger.rb +5 -3
- data/lib/clogger/pure.rb +14 -0
- data/test/test_clogger.rb +72 -2
- metadata +5 -7
data/GIT-VERSION-GEN
CHANGED
data/README
CHANGED
@@ -73,9 +73,10 @@ that receives a "<<" method:
|
|
73
73
|
(including response body iteration). PRECISION defaults to 3
|
74
74
|
(milliseconds) if not specified but may be specified anywhere from
|
75
75
|
0(seconds) to 6(microseconds).
|
76
|
-
* $
|
77
|
-
|
78
|
-
* $
|
76
|
+
* $time_iso8601 - current local time in ISO 8601 format,
|
77
|
+
e.g. "1970-01-01T00:00:00+00:00"
|
78
|
+
* $time_local - current local time in Apache log format,
|
79
|
+
e.g. "01/Jan/1970:00:00:00 +0000"
|
79
80
|
* $usec - current time in seconds.microseconds since the Epoch
|
80
81
|
* $msec - current time in seconds.milliseconds since the Epoch
|
81
82
|
* $body_bytes_sent - bytes in the response body (Apache: %B)
|
@@ -110,7 +111,7 @@ development. Patches should always be sent inline
|
|
110
111
|
|
111
112
|
== CONTACT
|
112
113
|
|
113
|
-
All feedback (bug reports, user/development
|
114
|
+
All feedback (bug reports, user/development discussion, patches, pull
|
114
115
|
requests) go to the mailing list.
|
115
116
|
|
116
117
|
* mailto:clogger@librelist.com
|
data/ext/clogger_ext/clogger.c
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
# define _POSIX_C_SOURCE 200112L
|
18
18
|
#endif
|
19
19
|
#include <time.h>
|
20
|
+
#include <stdlib.h>
|
20
21
|
#include "ruby_1_9_compat.h"
|
21
22
|
#include "broken_system_compat.h"
|
22
23
|
#include "blocking_helpers.h"
|
@@ -89,7 +90,10 @@ enum clogger_special {
|
|
89
90
|
CL_SP_response_length,
|
90
91
|
CL_SP_ip,
|
91
92
|
CL_SP_pid,
|
92
|
-
CL_SP_request_uri
|
93
|
+
CL_SP_request_uri,
|
94
|
+
CL_SP_time_iso8601,
|
95
|
+
CL_SP_time_local,
|
96
|
+
CL_SP_time_utc
|
93
97
|
};
|
94
98
|
|
95
99
|
struct clogger {
|
@@ -443,6 +447,75 @@ static void append_request_length(struct clogger *c)
|
|
443
447
|
}
|
444
448
|
}
|
445
449
|
|
450
|
+
static long local_gmtoffset(struct tm *tm)
|
451
|
+
{
|
452
|
+
time_t t = time(NULL);
|
453
|
+
|
454
|
+
tzset();
|
455
|
+
localtime_r(&t, tm);
|
456
|
+
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
|
457
|
+
return tm->tm_gmtoff / 60;
|
458
|
+
#else
|
459
|
+
return -(tm->tm_isdst ? timezone - 3600 : timezone) / 60;
|
460
|
+
#endif
|
461
|
+
}
|
462
|
+
|
463
|
+
static void append_time_iso8601(struct clogger *c)
|
464
|
+
{
|
465
|
+
char buf[sizeof("1970-01-01T00:00:00+00:00")];
|
466
|
+
struct tm tm;
|
467
|
+
int nr;
|
468
|
+
long gmtoff = local_gmtoffset(&tm);
|
469
|
+
|
470
|
+
nr = snprintf(buf, sizeof(buf),
|
471
|
+
"%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
472
|
+
tm.tm_year + 1900, tm.tm_mon + 1,
|
473
|
+
tm.tm_mday, tm.tm_hour,
|
474
|
+
tm.tm_min, tm.tm_sec,
|
475
|
+
gmtoff < 0 ? '-' : '+',
|
476
|
+
abs(gmtoff / 60), abs(gmtoff % 60));
|
477
|
+
assert(nr == (sizeof(buf) - 1) && "snprintf fail");
|
478
|
+
rb_str_buf_cat(c->log_buf, buf, sizeof(buf) - 1);
|
479
|
+
}
|
480
|
+
|
481
|
+
static const char months[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0"
|
482
|
+
"Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
|
483
|
+
|
484
|
+
static void append_time_local(struct clogger *c)
|
485
|
+
{
|
486
|
+
char buf[sizeof("01/Jan/1970:00:00:00 +0000")];
|
487
|
+
struct tm tm;
|
488
|
+
int nr;
|
489
|
+
long gmtoff = local_gmtoffset(&tm);
|
490
|
+
|
491
|
+
nr = snprintf(buf, sizeof(buf),
|
492
|
+
"%02d/%s/%d:%02d:%02d:%02d %c%02d%02d",
|
493
|
+
tm.tm_mday, months + (tm.tm_mon * sizeof("Jan")),
|
494
|
+
tm.tm_year + 1900, tm.tm_hour,
|
495
|
+
tm.tm_min, tm.tm_sec,
|
496
|
+
gmtoff < 0 ? '-' : '+',
|
497
|
+
abs(gmtoff / 60), abs(gmtoff % 60));
|
498
|
+
assert(nr == (sizeof(buf) - 1) && "snprintf fail");
|
499
|
+
rb_str_buf_cat(c->log_buf, buf, sizeof(buf) - 1);
|
500
|
+
}
|
501
|
+
|
502
|
+
static void append_time_utc(struct clogger *c)
|
503
|
+
{
|
504
|
+
char buf[sizeof("01/Jan/1970:00:00:00 +0000")];
|
505
|
+
struct tm tm;
|
506
|
+
int nr;
|
507
|
+
time_t t = time(NULL);
|
508
|
+
|
509
|
+
gmtime_r(&t, &tm);
|
510
|
+
nr = snprintf(buf, sizeof(buf),
|
511
|
+
"%02d/%s/%d:%02d:%02d:%02d +0000",
|
512
|
+
tm.tm_mday, months + (tm.tm_mon * sizeof("Jan")),
|
513
|
+
tm.tm_year + 1900, tm.tm_hour,
|
514
|
+
tm.tm_min, tm.tm_sec);
|
515
|
+
assert(nr == (sizeof(buf) - 1) && "snprintf fail");
|
516
|
+
rb_str_buf_cat(c->log_buf, buf, sizeof(buf) - 1);
|
517
|
+
}
|
518
|
+
|
446
519
|
static void
|
447
520
|
append_time(struct clogger *c, enum clogger_opcode op, VALUE fmt, VALUE buf)
|
448
521
|
{
|
@@ -547,6 +620,15 @@ static void special_var(struct clogger *c, enum clogger_special var)
|
|
547
620
|
break;
|
548
621
|
case CL_SP_request_uri:
|
549
622
|
append_request_uri(c);
|
623
|
+
break;
|
624
|
+
case CL_SP_time_iso8601:
|
625
|
+
append_time_iso8601(c);
|
626
|
+
break;
|
627
|
+
case CL_SP_time_local:
|
628
|
+
append_time_local(c);
|
629
|
+
break;
|
630
|
+
case CL_SP_time_utc:
|
631
|
+
append_time_utc(c);
|
550
632
|
}
|
551
633
|
}
|
552
634
|
|
@@ -640,8 +722,8 @@ static void init_logger(struct clogger *c, VALUE path)
|
|
640
722
|
*
|
641
723
|
* Creates a new Clogger object that wraps +app+. +:logger+ may
|
642
724
|
* be any object that responds to the "<<" method with a string argument.
|
643
|
-
*
|
644
|
-
*
|
725
|
+
* Instead of +:logger+, +:path+ may be specified to be a :path of a File
|
726
|
+
* that will be opened in append mode.
|
645
727
|
*/
|
646
728
|
static VALUE clogger_init(int argc, VALUE *argv, VALUE self)
|
647
729
|
{
|
data/ext/clogger_ext/extconf.rb
CHANGED
@@ -24,7 +24,6 @@ begin
|
|
24
24
|
have_func('rb_str_set_len', 'ruby.h')
|
25
25
|
have_func('rb_thread_blocking_region', 'ruby.h')
|
26
26
|
have_func('rb_thread_io_blocking_region', 'ruby.h')
|
27
|
-
dir_config('clogger_ext')
|
28
27
|
create_makefile('clogger_ext')
|
29
28
|
rescue Object => err
|
30
29
|
warn "E: #{err.inspect}"
|
data/lib/clogger.rb
CHANGED
@@ -19,8 +19,6 @@ class Clogger
|
|
19
19
|
# support nginx variables that are less customizable than our own
|
20
20
|
ALIASES = {
|
21
21
|
'$request_time' => '$request_time{3}',
|
22
|
-
'$time_local' => '$time_local{%d/%b/%Y:%H:%M:%S %z}',
|
23
|
-
'$time_utc' => '$time_utc{%d/%b/%Y:%H:%M:%S %z}',
|
24
22
|
'$msec' => '$time{3}',
|
25
23
|
'$usec' => '$time{6}',
|
26
24
|
'$http_content_length' => '$content_length',
|
@@ -35,7 +33,10 @@ class Clogger
|
|
35
33
|
:response_length => 4, # like body_bytes_sent, except "-" instead of "0"
|
36
34
|
:ip => 5, # HTTP_X_FORWARDED_FOR || REMOTE_ADDR || -
|
37
35
|
:pid => 6, # getpid()
|
38
|
-
:request_uri => 7
|
36
|
+
:request_uri => 7,
|
37
|
+
:time_iso8601 => 8,
|
38
|
+
:time_local => 9,
|
39
|
+
:time_utc => 10,
|
39
40
|
}
|
40
41
|
|
41
42
|
private
|
@@ -55,6 +56,7 @@ private
|
|
55
56
|
\w*))?([^$]*)/x
|
56
57
|
|
57
58
|
def compile_format(str, opt = {})
|
59
|
+
str = Clogger::Format.const_get(str) if Symbol === str
|
58
60
|
longest_day = Time.at(26265600) # "Saturday, November 01, 1970 00:00:00"
|
59
61
|
rv = []
|
60
62
|
opt ||= {}
|
data/lib/clogger/pure.rb
CHANGED
@@ -135,6 +135,20 @@ private
|
|
135
135
|
env['REMOTE_ADDR'] || '-'
|
136
136
|
when :pid
|
137
137
|
$$.to_s
|
138
|
+
when :time_iso8601
|
139
|
+
Time.now.iso8601
|
140
|
+
when :time_local
|
141
|
+
t = Time.now
|
142
|
+
off = t.utc_offset
|
143
|
+
sign = off < 0 ? '-' : '+'
|
144
|
+
sprintf("%02d/%s/%d:%02d:%02d:%02d #{sign}%02d%02d",
|
145
|
+
t.mday, Time::RFC2822_MONTH_NAME[t.mon - 1],
|
146
|
+
t.year, t.hour, t.min, t.sec, *(off.abs / 60).divmod(60))
|
147
|
+
when :time_utc
|
148
|
+
t = Time.now.utc
|
149
|
+
sprintf("%02d/%s/%d:%02d:%02d:%02d +0000",
|
150
|
+
t.mday, Time::RFC2822_MONTH_NAME[t.mon - 1],
|
151
|
+
t.year, t.hour, t.min, t.sec)
|
138
152
|
else
|
139
153
|
raise "EDOOFUS #{special_nr}"
|
140
154
|
end
|
data/test/test_clogger.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
$stderr.sync = $stdout.sync = true
|
3
3
|
require "test/unit"
|
4
|
+
require "time"
|
4
5
|
require "date"
|
5
6
|
require "stringio"
|
6
7
|
require "tempfile"
|
@@ -17,6 +18,8 @@ class TestClogger < Test::Unit::TestCase
|
|
17
18
|
include Clogger::Format
|
18
19
|
|
19
20
|
def setup
|
21
|
+
@tz = ENV["TZ"]
|
22
|
+
@nginx_fmt = "%d/%b/%Y:%H:%M:%S %z"
|
20
23
|
@req = {
|
21
24
|
"REQUEST_METHOD" => "GET",
|
22
25
|
"HTTP_VERSION" => "HTTP/1.0",
|
@@ -29,6 +32,10 @@ class TestClogger < Test::Unit::TestCase
|
|
29
32
|
}
|
30
33
|
end
|
31
34
|
|
35
|
+
def teardown
|
36
|
+
ENV["TZ"] = @tz
|
37
|
+
end
|
38
|
+
|
32
39
|
def test_init_basic
|
33
40
|
Clogger.new(lambda { |env| [ 0, {}, [] ] })
|
34
41
|
end
|
@@ -37,6 +44,11 @@ class TestClogger < Test::Unit::TestCase
|
|
37
44
|
assert_raise(ArgumentError) { Clogger.new }
|
38
45
|
end
|
39
46
|
|
47
|
+
def test_clogger_sym_format
|
48
|
+
app = lambda { |env| [ 0, {}, [] ] }
|
49
|
+
tmp = Clogger.new app, :format => :Rack_1_0, :logger => $stderr
|
50
|
+
end
|
51
|
+
|
40
52
|
def test_init_stderr
|
41
53
|
cl = Clogger.new(lambda { |env| [ 0, {}, [] ] }, :logger => $stderr)
|
42
54
|
assert_kind_of(Integer, cl.fileno)
|
@@ -156,13 +168,12 @@ class TestClogger < Test::Unit::TestCase
|
|
156
168
|
'$env{rack.url_scheme}' \
|
157
169
|
"\n")
|
158
170
|
}
|
159
|
-
longest_day = Time.at(26265600).strftime('%d/%b/%Y:%H:%M:%S %z')
|
160
171
|
expect = [
|
161
172
|
[ Clogger::OP_REQUEST, "REMOTE_ADDR" ],
|
162
173
|
[ Clogger::OP_LITERAL, " - " ],
|
163
174
|
[ Clogger::OP_REQUEST, "REMOTE_USER" ],
|
164
175
|
[ Clogger::OP_LITERAL, " [" ],
|
165
|
-
[ Clogger::
|
176
|
+
[ Clogger::OP_SPECIAL, Clogger::SPECIAL_VARS[:time_local] ],
|
166
177
|
[ Clogger::OP_LITERAL, "] \"" ],
|
167
178
|
[ Clogger::OP_SPECIAL, Clogger::SPECIAL_VARS[:request] ],
|
168
179
|
[ Clogger::OP_LITERAL, "\" "],
|
@@ -698,6 +709,65 @@ class TestClogger < Test::Unit::TestCase
|
|
698
709
|
assert %r!\A\d+/\w+/\d{4}:\d\d:\d\d:\d\d \+0000\n\z! =~ s[0], s.inspect
|
699
710
|
end
|
700
711
|
|
712
|
+
def test_time_iso8601
|
713
|
+
s = []
|
714
|
+
app = lambda { |env| [200, [], [] ] }
|
715
|
+
cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
|
716
|
+
status, headers, body = cl.call(@req)
|
717
|
+
t = Time.parse(s[0])
|
718
|
+
assert_equal t.iso8601, s[0].strip
|
719
|
+
end
|
720
|
+
|
721
|
+
def test_time_iso8601_pst8pdt
|
722
|
+
ENV["TZ"] = "PST8PDT"
|
723
|
+
s = []
|
724
|
+
app = lambda { |env| [200, [], [] ] }
|
725
|
+
cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
|
726
|
+
status, headers, body = cl.call(@req)
|
727
|
+
t = Time.parse(s[0])
|
728
|
+
assert_equal t.iso8601, s[0].strip
|
729
|
+
end
|
730
|
+
|
731
|
+
def test_time_iso8601_utc
|
732
|
+
ENV["TZ"] = "UTC"
|
733
|
+
s = []
|
734
|
+
app = lambda { |env| [200, [], [] ] }
|
735
|
+
cl = Clogger.new(app, :logger => s, :format => "$time_iso8601")
|
736
|
+
status, headers, body = cl.call(@req)
|
737
|
+
t = Time.parse(s[0])
|
738
|
+
assert_equal t.iso8601, s[0].strip
|
739
|
+
end
|
740
|
+
|
741
|
+
def test_time_local
|
742
|
+
s = []
|
743
|
+
app = lambda { |env| [200, [], [] ] }
|
744
|
+
cl = Clogger.new(app, :logger => s, :format => "$time_local")
|
745
|
+
status, headers, body = cl.call(@req)
|
746
|
+
t = DateTime.strptime(s[0].strip, @nginx_fmt)
|
747
|
+
assert_equal t.strftime(@nginx_fmt), s[0].strip
|
748
|
+
end
|
749
|
+
|
750
|
+
def test_time_local_pst8pdt
|
751
|
+
orig = ENV["TZ"]
|
752
|
+
ENV["TZ"] = "PST8PDT"
|
753
|
+
s = []
|
754
|
+
app = lambda { |env| [200, [], [] ] }
|
755
|
+
cl = Clogger.new(app, :logger => s, :format => "$time_local")
|
756
|
+
status, headers, body = cl.call(@req)
|
757
|
+
t = DateTime.strptime(s[0].strip, @nginx_fmt)
|
758
|
+
assert_equal t.strftime(@nginx_fmt), s[0].strip
|
759
|
+
end
|
760
|
+
|
761
|
+
def test_time_local_utc
|
762
|
+
ENV["TZ"] = "UTC"
|
763
|
+
s = []
|
764
|
+
app = lambda { |env| [200, [], [] ] }
|
765
|
+
cl = Clogger.new(app, :logger => s, :format => "$time_local")
|
766
|
+
status, headers, body = cl.call(@req)
|
767
|
+
t = DateTime.strptime(s[0].strip, @nginx_fmt)
|
768
|
+
assert_equal t.strftime(@nginx_fmt), s[0].strip
|
769
|
+
end
|
770
|
+
|
701
771
|
def test_method_missing
|
702
772
|
s = []
|
703
773
|
body = []
|
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:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
- 9
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 1.0.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- cloggers
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-04-21 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: rack
|
@@ -94,7 +93,6 @@ files:
|
|
94
93
|
- setup.rb
|
95
94
|
- test/test_clogger.rb
|
96
95
|
- test/test_clogger_to_path.rb
|
97
|
-
has_rdoc: true
|
98
96
|
homepage: http://clogger.rubyforge.org/
|
99
97
|
licenses: []
|
100
98
|
|
@@ -128,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
126
|
requirements: []
|
129
127
|
|
130
128
|
rubyforge_project: clogger
|
131
|
-
rubygems_version: 1.
|
129
|
+
rubygems_version: 1.7.2
|
132
130
|
signing_key:
|
133
131
|
specification_version: 3
|
134
132
|
summary: configurable request logging for Rack
|