clogger 0.9.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|