logfile_interval 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/Gemfile.lock +4 -4
- data/README.md +3 -6
- data/docs/design.rb +118 -36
- data/lib/logfile_interval/aggregator/average.rb +14 -0
- data/lib/logfile_interval/aggregator/base.rb +52 -0
- data/lib/logfile_interval/aggregator/count.rb +9 -0
- data/lib/logfile_interval/aggregator/delta.rb +22 -0
- data/lib/logfile_interval/aggregator/group_and_count.rb +14 -0
- data/lib/logfile_interval/aggregator/sum.rb +9 -0
- data/lib/logfile_interval/aggregator.rb +24 -0
- data/lib/logfile_interval/interval.rb +9 -0
- data/lib/logfile_interval/interval_builder.rb +2 -0
- data/lib/logfile_interval/logfile.rb +4 -1
- data/lib/logfile_interval/logfile_set.rb +4 -0
- data/lib/logfile_interval/{line_parser → util}/counter.rb +1 -1
- data/lib/logfile_interval/util/file_backward.rb +51 -0
- data/lib/logfile_interval/version.rb +1 -1
- data/lib/logfile_interval.rb +3 -3
- data/spec/lib/aggregator_spec.rb +208 -0
- data/spec/lib/{line_parser/counter_spec.rb → counter_spec.rb} +1 -1
- data/spec/lib/interval_builder_spec.rb +8 -0
- data/spec/lib/interval_spec.rb +31 -7
- data/spec/lib/logfile_set_spec.rb +39 -14
- data/spec/lib/logfile_spec.rb +43 -18
- metadata +15 -12
- data/docs/design2.rb +0 -77
- data/docs/design3.rb +0 -177
- data/lib/logfile_interval/file_backward.rb +0 -49
- data/lib/logfile_interval/interval_length.rb +0 -47
- data/lib/logfile_interval/line_parser/aggregator.rb +0 -117
- data/spec/lib/line_parser/aggregator_spec.rb +0 -211
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LogfileInterval
|
4
|
+
module Aggregator
|
5
|
+
describe Aggregator do
|
6
|
+
it 'finds the aggregator class' do
|
7
|
+
Aggregator.klass(:sum).should == Sum
|
8
|
+
Aggregator.klass(:average).should == Average
|
9
|
+
Aggregator.klass(:count).should == Count
|
10
|
+
Aggregator.klass(:group_and_count).should == GroupAndCount
|
11
|
+
Aggregator.klass(:delta).should == Delta
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
shared_examples 'an aggregator' do
|
16
|
+
let(:aggregator) { described_class.new }
|
17
|
+
|
18
|
+
[ :add, :value, :values ].each do |method|
|
19
|
+
it "responds to #{method}" do
|
20
|
+
aggregator.should respond_to(method)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'values' do
|
25
|
+
context 'with one group' do
|
26
|
+
before :each do
|
27
|
+
aggregator.add(5, :key1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns a hash' do
|
31
|
+
aggregator.values.should be_a(Hash) unless aggregator.is_a?(Delta)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with several groups' do
|
36
|
+
before :each do
|
37
|
+
aggregator.add(5, :key1)
|
38
|
+
aggregator.add(3, :key2)
|
39
|
+
aggregator.add(3, :key1)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns a hash' do
|
43
|
+
aggregator.values.should be_a(Hash)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with no group' do
|
48
|
+
before :each do
|
49
|
+
aggregator.add(5)
|
50
|
+
aggregator.add(3)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns a numeric' do
|
54
|
+
aggregator.values.should be_a(Numeric) unless aggregator.is_a?(Count)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
[ Count, Sum, Average, Delta ]. each do |klass|
|
61
|
+
describe klass do
|
62
|
+
it_behaves_like 'an aggregator'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
describe 'without group_by key' do
|
68
|
+
describe Sum do
|
69
|
+
it 'sums up values' do
|
70
|
+
sum = Sum.new
|
71
|
+
sum.add(3)
|
72
|
+
sum.add(5)
|
73
|
+
sum.value.should == 8
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe Average do
|
78
|
+
it 'averages values' do
|
79
|
+
avg = Average.new
|
80
|
+
avg.add(3)
|
81
|
+
avg.add(5)
|
82
|
+
avg.value.should == 4
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe Delta do
|
87
|
+
it 'averages delta values' do
|
88
|
+
d = Delta.new
|
89
|
+
d.add(1.4)
|
90
|
+
d.add(1.1)
|
91
|
+
d.add(1.0)
|
92
|
+
d.value.round(5).should == 0.2
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe Count do
|
97
|
+
it 'groups values and increment counters' do
|
98
|
+
g = Count.new
|
99
|
+
g.add('200')
|
100
|
+
g.add('500')
|
101
|
+
g.add('301')
|
102
|
+
g.add('200')
|
103
|
+
g.value.should == 4
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'with group_by key' do
|
109
|
+
|
110
|
+
describe Sum do
|
111
|
+
it 'sums up values by key' do
|
112
|
+
sum = Sum.new
|
113
|
+
sum.add(3, :key1)
|
114
|
+
sum.add(5, :key2)
|
115
|
+
sum.add(5, :key1)
|
116
|
+
sum.values.should be_a(Hash)
|
117
|
+
sum.values.size.should == 2
|
118
|
+
sum.value(:key1).should == 8
|
119
|
+
sum.values[:key1].should == 8
|
120
|
+
sum.value(:key2).should == 5
|
121
|
+
sum.values[:key2].should == 5
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
describe Average do
|
127
|
+
it 'averages values by key' do
|
128
|
+
avg = Average.new
|
129
|
+
avg.add(3, :key1)
|
130
|
+
avg.add(5, :key2)
|
131
|
+
avg.add(5, :key1)
|
132
|
+
avg.values.should be_a(Hash)
|
133
|
+
avg.values.size.should == 2
|
134
|
+
avg.value(:key1).should == 4
|
135
|
+
avg.values[:key1].should == 4
|
136
|
+
avg.value(:key2).should == 5
|
137
|
+
avg.values[:key2].should == 5
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe Count do
|
142
|
+
it 'groups values and increment counters' do
|
143
|
+
g = Count.new
|
144
|
+
g.add('200', '200')
|
145
|
+
g.add('500', '500')
|
146
|
+
g.add('301', '301')
|
147
|
+
g.add('200', '200')
|
148
|
+
g.values.should be_a(Hash)
|
149
|
+
g.values.should include({'200' => 2})
|
150
|
+
g.values.should include({'301' => 1})
|
151
|
+
g.values.should include({'500' => 1})
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe GroupAndCount do
|
156
|
+
it 'each yields a key and a hash' do
|
157
|
+
gac = GroupAndCount.new
|
158
|
+
gac.add :key1, :subkey1
|
159
|
+
gac.first.should be_an(Array)
|
160
|
+
gac.first.size.should == 2
|
161
|
+
gac.first[1].should be_a(Hash)
|
162
|
+
end
|
163
|
+
|
164
|
+
context :add do
|
165
|
+
before :each do
|
166
|
+
@gac = GroupAndCount.new
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'requires a group_by argument' do
|
170
|
+
lambda { @gac.add('foo') }.should raise_error ArgumentError
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'counts number of occurence of subkey for key' do
|
174
|
+
@gac.add :key1, :subkey1
|
175
|
+
@gac.add :key1, :subkey2
|
176
|
+
@gac.add :key2, :subkey1
|
177
|
+
@gac.add :key2, :subkey1
|
178
|
+
@gac.add :key2, :subkey3
|
179
|
+
|
180
|
+
@gac.values[:key1][:subkey1].should == 1
|
181
|
+
@gac.values[:key1][:subkey2].should == 1
|
182
|
+
@gac.values[:key2][:subkey1].should == 2
|
183
|
+
@gac.values[:key2][:subkey2].should == 0
|
184
|
+
@gac.values[:key2][:subkey3].should == 1
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe Delta do
|
190
|
+
it 'averages deltas by key' do
|
191
|
+
d = Delta.new
|
192
|
+
d.add(9, :key1)
|
193
|
+
d.add(10, :key2)
|
194
|
+
d.add(5, :key1)
|
195
|
+
d.add(8, :key2)
|
196
|
+
d.add(3, :key1)
|
197
|
+
d.add(5, :key2)
|
198
|
+
d.values.should be_a(Hash)
|
199
|
+
d.values.size.should == 2
|
200
|
+
d.value(:key1).should == 3
|
201
|
+
d.values[:key1].should == 3
|
202
|
+
d.value(:key2).should == 2.5
|
203
|
+
d.values[:key2].should == 2.5
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -47,6 +47,14 @@ module LogfileInterval
|
|
47
47
|
@intervals.last[:action].should == 2
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
context 'without a block' do
|
52
|
+
it 'should return an iterator' do
|
53
|
+
e = @builder.each_interval
|
54
|
+
e.should be_an(Enumerator)
|
55
|
+
e.next.end_time.should == Time.new(2013,12,01,16,0,0,'-08:00')
|
56
|
+
end
|
57
|
+
end
|
50
58
|
end
|
51
59
|
|
52
60
|
context :last_interval do
|
data/spec/lib/interval_spec.rb
CHANGED
@@ -5,9 +5,13 @@ module LogfileInterval
|
|
5
5
|
data_dir = File.join(File.dirname(__FILE__), '..', 'support/logfiles')
|
6
6
|
|
7
7
|
describe Interval do
|
8
|
+
before :each do
|
9
|
+
@end_time = Time.new(2013, 12, 01, 16, 00, 00, '-08:00')
|
10
|
+
@length = 300
|
11
|
+
end
|
12
|
+
|
8
13
|
it 'gets instantiated with empty data' do
|
9
|
-
|
10
|
-
interval = Interval.new(end_time, 300, LineParser::TimingLog)
|
14
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
11
15
|
interval.size.should == 0
|
12
16
|
interval[:total_time].should == 0
|
13
17
|
interval[:num_bytes].should == 0
|
@@ -15,12 +19,32 @@ module LogfileInterval
|
|
15
19
|
interval[:ip].should == 0
|
16
20
|
end
|
17
21
|
|
18
|
-
context :
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
context :to_hash do
|
23
|
+
it 'returns a hash' do
|
24
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
25
|
+
interval.to_hash.should be_a(Hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has a key for all columns' do
|
29
|
+
record = LineParser::TimingLog.create_record('1385942400, 192.168.0.5, posts#index, 100, 2000, 53.0')
|
30
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
31
|
+
interval.add_record(record)
|
32
|
+
hinterval = interval.to_hash
|
33
|
+
hinterval.keys.should include(:ip, :total_time, :action, :num_bytes, :rss)
|
22
34
|
end
|
23
35
|
|
36
|
+
it 'with no data, should have keys with 0 values' do
|
37
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
38
|
+
hinterval = interval.to_hash
|
39
|
+
hinterval[:ip].should == 0
|
40
|
+
hinterval[:action].should == 0
|
41
|
+
hinterval[:total_time].should == 0
|
42
|
+
hinterval[:num_bytes].should == 0
|
43
|
+
hinterval[:rss].should == 0
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context :add_record do
|
24
48
|
context 'basics' do
|
25
49
|
before :each do
|
26
50
|
@interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
@@ -50,7 +74,7 @@ module LogfileInterval
|
|
50
74
|
|
51
75
|
context 'with count and group by options' do
|
52
76
|
it 'creates an aggregator of type GroupAndCount' do
|
53
|
-
expect(
|
77
|
+
expect(Aggregator::GroupAndCount).to receive(:new)
|
54
78
|
interval = Interval.new(@end_time, @length, LineParser::TimingLogWithGrouping)
|
55
79
|
end
|
56
80
|
|
@@ -8,32 +8,57 @@ module LogfileInterval
|
|
8
8
|
before :each do
|
9
9
|
@logfiles = ["#{data_dir}/access.log.2", "#{data_dir}/access.log.1"]
|
10
10
|
@set = LogfileSet.new(@logfiles, LineParser::AccessLog)
|
11
|
+
@first_line = '66.249.67.176 - - [23/Jun/2013:17:00:01 -0800] "GET /package/core/raring/universe/proposed/openldap HTTP/1.1" 200 185 "-" "Google"'
|
12
|
+
@second_line = '12.24.48.96 - - [23/Jun/2013:16:59:00 -0800] "GET /package/core/raring/universe/proposed/openldap HTTP/1.1" 200 4555 "-" "Bing)"'
|
13
|
+
@last_line = '12.24.48.96 - - [23/Jun/2013:16:49:00 -0800] "GET /package/core/raring/universe/proposed/bash HTTP/1.1" 200 4555 "-" "Bing)"'
|
11
14
|
end
|
12
15
|
|
13
16
|
it 'ordered_filenames should return the most recent file first' do
|
14
17
|
@set.ordered_filenames.should == @logfiles.reverse
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
describe :each_line do
|
21
|
+
it 'should enumerate each line in file backwards' do
|
22
|
+
lines = []
|
23
|
+
@set.each_line do |line|
|
24
|
+
lines << line
|
25
|
+
end
|
26
|
+
|
27
|
+
lines.first.should == @first_line
|
28
|
+
lines.last.should == @last_line
|
21
29
|
end
|
22
30
|
|
23
|
-
|
24
|
-
|
31
|
+
context 'without a block' do
|
32
|
+
it 'should return an enumerator' do
|
33
|
+
e = @set.each_line
|
34
|
+
e.should be_a(Enumerator)
|
35
|
+
e.first.should == @first_line
|
36
|
+
e.next.should == @first_line
|
37
|
+
e.next.should == @second_line
|
38
|
+
end
|
39
|
+
end
|
25
40
|
end
|
26
41
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
describe :each_parsed_line do
|
43
|
+
it 'should enumerate each line backwards' do
|
44
|
+
records = []
|
45
|
+
@set.each_parsed_line do |record|
|
46
|
+
records << record
|
47
|
+
end
|
48
|
+
|
49
|
+
records.first.time.should == Time.new(2013, 06, 23, 17, 00, 01, '-08:00')
|
50
|
+
records.first.code.should == '200'
|
51
|
+
records.last.time.should == Time.new(2013, 06, 23, 16, 49, 00, '-08:00')
|
52
|
+
records.last.code.should == '200'
|
31
53
|
end
|
32
54
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
55
|
+
context 'without a block' do
|
56
|
+
it 'should return an enumerator' do
|
57
|
+
e = @set.each_parsed_line
|
58
|
+
e.should be_a(Enumerator)
|
59
|
+
e.next.time.should == Time.new(2013, 06, 23, 17, 00, 01, '-08:00')
|
60
|
+
end
|
61
|
+
end
|
37
62
|
end
|
38
63
|
end
|
39
64
|
end
|
data/spec/lib/logfile_spec.rb
CHANGED
@@ -7,6 +7,9 @@ module LogfileInterval
|
|
7
7
|
describe Logfile do
|
8
8
|
before :each do
|
9
9
|
@alf = Logfile.new("#{data_dir}/access.log", LineParser::AccessLog)
|
10
|
+
@first_line = '78.54.172.146 - - [01/Jan/2012:16:30:51 -0800] "GET /package/core/oneiric/main/base/abrowser-6.0 HTTP/1.1" 200 6801 "http://www.google.com/url?sa=t&rct=j&q=abrowser 6.0&esrc=s&source=web&cd=4&sqi=2&ved=0CDYQFjAD&url=http%3A%2F%2Fwww.ubuntuupdates.org%2Fpackages%2Fshow%2F268762&ei=s-QlT8vJFon1sgb54unBDg&usg=AFQjCNHCHC0bxTf6aXAfUwT6Erjta6WLaQ&sig2=ceCi1odtaB8Vcf6IWg2a3w" "Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"'
|
11
|
+
@second_line = '78.54.172.146 - - [01/Jan/2012:16:30:51 -0800] "GET /package/show/2 HTTP/1.1" 302 6801 "http://www.google.com/url?sa=t&rct=j&q=abrowser 6.0&esrc=s&source=web&cd=4&sqi=2&ved=0CDYQFjAD&url=http%3A%2F%2Fwww.ubuntuupdates.org%2Fpackages%2Fshow%2F268762&ei=s-QlT8vJFon1sgb54unBDg&usg=AFQjCNHCHC0bxTf6aXAfUwT6Erjta6WLaQ&sig2=ceCi1odtaB8Vcf6IWg2a3w" "Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"'
|
12
|
+
@last_line = '66.249.67.176 - - [01/Jan/2012:00:57:47 -0800] "GET /packages/show/1 HTTP/1.1" 301 185 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"'
|
10
13
|
end
|
11
14
|
|
12
15
|
it 'first_timestamp returns time of first line in file' do
|
@@ -14,30 +17,52 @@ module LogfileInterval
|
|
14
17
|
@alf.first_timestamp.should == Time.new(2012, 01, 01, 00, 57, 47, '-08:00')
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
describe :each_line do
|
21
|
+
it 'should enumerate each line in file backwards' do
|
22
|
+
lines = []
|
23
|
+
@alf.each_line do |line|
|
24
|
+
lines << line
|
25
|
+
end
|
26
|
+
|
27
|
+
lines.first.should == @first_line
|
28
|
+
lines.last.should == @last_line
|
21
29
|
end
|
22
30
|
|
23
|
-
|
24
|
-
|
31
|
+
context 'without a block' do
|
32
|
+
it 'should return an enumerator' do
|
33
|
+
e = @alf.each_line
|
34
|
+
e.should be_a(Enumerator)
|
35
|
+
e.first.should == @first_line
|
36
|
+
e.next.should == @first_line
|
37
|
+
e.next.should == @second_line
|
38
|
+
end
|
39
|
+
end
|
25
40
|
end
|
26
41
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
describe :each_parsed_line do
|
43
|
+
it 'should enumerate each line backwards' do
|
44
|
+
records = []
|
45
|
+
@alf.each_parsed_line do |record|
|
46
|
+
records << record
|
47
|
+
end
|
48
|
+
|
49
|
+
records.first.time.should == Time.new(2012, 01, 01, 16, 30, 51, '-08:00')
|
50
|
+
records.first.code.should == '200'
|
51
|
+
records.first.length.should == 6801
|
52
|
+
records.first.length_by_ip.should == 6801
|
53
|
+
records.last.time.should == Time.new(2012, 01, 01, 00, 57, 47, '-08:00')
|
54
|
+
records.last.code.should == '301'
|
55
|
+
records.last.length.should == 185
|
56
|
+
records.last.length_by_ip.should == 185
|
31
57
|
end
|
32
58
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
records.last.length_by_ip.should == 185
|
59
|
+
context 'without a block' do
|
60
|
+
it 'should return an enumerator' do
|
61
|
+
e = @alf.each_parsed_line
|
62
|
+
e.should be_a(Enumerator)
|
63
|
+
e.next.time.should == Time.new(2012, 01, 01, 16, 30, 51, '-08:00')
|
64
|
+
end
|
65
|
+
end
|
41
66
|
end
|
42
67
|
end
|
43
68
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logfile_interval
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Philippe Le Rohellec
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -99,25 +99,28 @@ files:
|
|
99
99
|
- bin/aggregate_access_log.rb
|
100
100
|
- bin/readme.rb
|
101
101
|
- docs/design.rb
|
102
|
-
- docs/design2.rb
|
103
|
-
- docs/design3.rb
|
104
102
|
- lib/logfile_interval.rb
|
105
|
-
- lib/logfile_interval/
|
103
|
+
- lib/logfile_interval/aggregator.rb
|
104
|
+
- lib/logfile_interval/aggregator/average.rb
|
105
|
+
- lib/logfile_interval/aggregator/base.rb
|
106
|
+
- lib/logfile_interval/aggregator/count.rb
|
107
|
+
- lib/logfile_interval/aggregator/delta.rb
|
108
|
+
- lib/logfile_interval/aggregator/group_and_count.rb
|
109
|
+
- lib/logfile_interval/aggregator/sum.rb
|
106
110
|
- lib/logfile_interval/interval.rb
|
107
111
|
- lib/logfile_interval/interval_builder.rb
|
108
|
-
- lib/logfile_interval/interval_length.rb
|
109
|
-
- lib/logfile_interval/line_parser/aggregator.rb
|
110
112
|
- lib/logfile_interval/line_parser/base.rb
|
111
|
-
- lib/logfile_interval/line_parser/counter.rb
|
112
113
|
- lib/logfile_interval/logfile.rb
|
113
114
|
- lib/logfile_interval/logfile_set.rb
|
115
|
+
- lib/logfile_interval/util/counter.rb
|
116
|
+
- lib/logfile_interval/util/file_backward.rb
|
114
117
|
- lib/logfile_interval/version.rb
|
115
118
|
- logfile_interval.gemspec
|
119
|
+
- spec/lib/aggregator_spec.rb
|
120
|
+
- spec/lib/counter_spec.rb
|
116
121
|
- spec/lib/interval_builder_spec.rb
|
117
122
|
- spec/lib/interval_spec.rb
|
118
|
-
- spec/lib/line_parser/aggregator_spec.rb
|
119
123
|
- spec/lib/line_parser/base_spec.rb
|
120
|
-
- spec/lib/line_parser/counter_spec.rb
|
121
124
|
- spec/lib/logfile_set_spec.rb
|
122
125
|
- spec/lib/logfile_spec.rb
|
123
126
|
- spec/spec_helper.rb
|
@@ -154,11 +157,11 @@ signing_key:
|
|
154
157
|
specification_version: 4
|
155
158
|
summary: Aggregate logfile data into intervals
|
156
159
|
test_files:
|
160
|
+
- spec/lib/aggregator_spec.rb
|
161
|
+
- spec/lib/counter_spec.rb
|
157
162
|
- spec/lib/interval_builder_spec.rb
|
158
163
|
- spec/lib/interval_spec.rb
|
159
|
-
- spec/lib/line_parser/aggregator_spec.rb
|
160
164
|
- spec/lib/line_parser/base_spec.rb
|
161
|
-
- spec/lib/line_parser/counter_spec.rb
|
162
165
|
- spec/lib/logfile_set_spec.rb
|
163
166
|
- spec/lib/logfile_spec.rb
|
164
167
|
- spec/spec_helper.rb
|
data/docs/design2.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module LogfileInterval
|
2
|
-
class Logfile
|
3
|
-
end
|
4
|
-
|
5
|
-
class LogfileSet
|
6
|
-
end
|
7
|
-
|
8
|
-
class Interval
|
9
|
-
end
|
10
|
-
|
11
|
-
class LineParser
|
12
|
-
def initialize(regex, columns)
|
13
|
-
end
|
14
|
-
|
15
|
-
def parse(line)
|
16
|
-
@data = {}
|
17
|
-
|
18
|
-
match_data = regex.match(line)
|
19
|
-
columns.each do |name, options|
|
20
|
-
val = match_data[options[:pos]]
|
21
|
-
@data[name] = convert(val, options[:conversion])
|
22
|
-
end
|
23
|
-
@data
|
24
|
-
end
|
25
|
-
|
26
|
-
def convert(val, conversion)
|
27
|
-
case options[:conversion]
|
28
|
-
when :integer then val.to_i
|
29
|
-
else val
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class Record
|
35
|
-
def initialize(parser, line)
|
36
|
-
@parser = parser
|
37
|
-
@data = parser.parse(line)
|
38
|
-
end
|
39
|
-
|
40
|
-
def valid_columns
|
41
|
-
@parser.columns.keys
|
42
|
-
end
|
43
|
-
|
44
|
-
def method_missing(meth, *args)
|
45
|
-
if valid_columns.include?(meth) && args.none
|
46
|
-
self[meth]
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
logfiles = [ 'access.log', 'access.log.1', 'access.log.2' ]
|
55
|
-
logfile = logfiles.first
|
56
|
-
parser = LineParser.new(/blah/, [ { :name=>:ip , :pos => 1 }, ...])
|
57
|
-
|
58
|
-
logfile_iterator = LogfileInterval::Logfile.new(parser, logfile)
|
59
|
-
|
60
|
-
logfile_iterator.each_line do |line|
|
61
|
-
puts line
|
62
|
-
end
|
63
|
-
|
64
|
-
logfile_iterator.each_parsed_line do |record|
|
65
|
-
puts record.ip
|
66
|
-
puts record.time
|
67
|
-
end
|
68
|
-
|
69
|
-
interval_builder = LogfileInterval::Interval.new(parser, logfiles)
|
70
|
-
|
71
|
-
interval_builder.each_interval do |interval|
|
72
|
-
puts interval.start_time
|
73
|
-
puts interval.length
|
74
|
-
interval[:ip].each do |ip, count|
|
75
|
-
puts "#{ip}, #{count}"
|
76
|
-
end
|
77
|
-
end
|